diff options
1022 files changed, 19532 insertions, 5883 deletions
diff --git a/Android.bp b/Android.bp index df6fdaa5fdf6..6892205e9a8f 100644 --- a/Android.bp +++ b/Android.bp @@ -265,6 +265,60 @@ java_defaults { ], aidl: { generate_get_transaction_name: true, + enforce_permissions: true, + enforce_permissions_exceptions: [ + // Do not add entries to this list. + ":framework-annotations", + ":framework-blobstore-sources", + ":framework-core-sources", + ":framework-drm-sources", + ":framework-graphics-nonupdatable-sources", + ":framework-jobscheduler-sources", + ":framework-keystore-sources", + ":framework-identity-sources", + ":framework-location-sources", + ":framework-lowpan-sources", + ":framework-mca-effect-sources", + ":framework-mca-filterfw-sources", + ":framework-mca-filterpacks-sources", + ":framework-media-non-updatable-sources", + ":framework-mms-sources", + ":framework-omapi-sources", + ":framework-opengl-sources", + ":framework-rs-sources", + ":framework-sax-sources", + ":framework-telecomm-sources", + ":framework-telephony-common-sources", + ":framework-telephony-sources", + ":framework-vcn-util-sources", + ":framework-wifi-annotations", + ":framework-wifi-non-updatable-sources", + ":PacProcessor-aidl-sources", + ":ProxyHandler-aidl-sources", + ":net-utils-framework-common-srcs", + ":platform-compat-native-aidl", + ":credstore_aidl", + ":dumpstate_aidl", + ":framework_native_aidl", + ":gatekeeper_aidl", + ":gsiservice_aidl", + ":idmap2_aidl", + ":idmap2_core_aidl", + ":incidentcompanion_aidl", + ":inputconstants_aidl", + ":installd_aidl", + ":libaudioclient_aidl", + ":libbinder_aidl", + ":libbluetooth-binder-aidl", + ":libcamera_client_aidl", + ":libcamera_client_framework_aidl", + ":libupdate_engine_aidl", + ":logd_aidl", + ":resourcemanager_aidl", + ":storaged_aidl", + ":vold_aidl", + ":deviceproductinfoconstants_aidl", + ], local_include_dirs: [ "media/aidl", ], diff --git a/apct-tests/perftests/core/src/android/view/HandwritingInitiatorPerfTest.java b/apct-tests/perftests/core/src/android/view/HandwritingInitiatorPerfTest.java index 4cd974141d26..086e18594615 100644 --- a/apct-tests/perftests/core/src/android/view/HandwritingInitiatorPerfTest.java +++ b/apct-tests/perftests/core/src/android/view/HandwritingInitiatorPerfTest.java @@ -27,6 +27,7 @@ import android.app.Instrumentation; import android.content.Context; import android.perftests.utils.BenchmarkState; import android.perftests.utils.PerfStatusReporter; +import android.util.DisplayMetrics; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; @@ -59,10 +60,13 @@ public class HandwritingInitiatorPerfTest { public void setup() { final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation(); mContext = mInstrumentation.getTargetContext(); - ViewConfiguration viewConfiguration = ViewConfiguration.get(mContext); + final ViewConfiguration viewConfiguration = ViewConfiguration.get(mContext); mTouchSlop = viewConfiguration.getScaledTouchSlop(); - InputMethodManager inputMethodManager = mContext.getSystemService(InputMethodManager.class); - mHandwritingInitiator = new HandwritingInitiator(viewConfiguration, inputMethodManager); + final InputMethodManager inputMethodManager = + mContext.getSystemService(InputMethodManager.class); + final DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics(); + mHandwritingInitiator = new HandwritingInitiator(viewConfiguration, inputMethodManager, + displayMetrics); } @Test diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index fb68c6d84d6a..8a7e598e27ab 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -71,8 +71,6 @@ static const char PRODUCT_BOOTANIMATION_DARK_FILE[] = "/product/media/bootanimat static const char PRODUCT_BOOTANIMATION_FILE[] = "/product/media/bootanimation.zip"; static const char SYSTEM_BOOTANIMATION_FILE[] = "/system/media/bootanimation.zip"; static const char APEX_BOOTANIMATION_FILE[] = "/apex/com.android.bootanimation/etc/bootanimation.zip"; -static const char PRODUCT_ENCRYPTED_BOOTANIMATION_FILE[] = "/product/media/bootanimation-encrypted.zip"; -static const char SYSTEM_ENCRYPTED_BOOTANIMATION_FILE[] = "/system/media/bootanimation-encrypted.zip"; static const char OEM_SHUTDOWNANIMATION_FILE[] = "/oem/media/shutdownanimation.zip"; static const char PRODUCT_SHUTDOWNANIMATION_FILE[] = "/product/media/shutdownanimation.zip"; static const char SYSTEM_SHUTDOWNANIMATION_FILE[] = "/system/media/shutdownanimation.zip"; @@ -653,23 +651,6 @@ bool BootAnimation::findBootAnimationFileInternal(const std::vector<std::string> } void BootAnimation::findBootAnimationFile() { - // If the device has encryption turned on or is in process - // of being encrypted we show the encrypted boot animation. - char decrypt[PROPERTY_VALUE_MAX]; - property_get("vold.decrypt", decrypt, ""); - - bool encryptedAnimation = atoi(decrypt) != 0 || - !strcmp("trigger_restart_min_framework", decrypt); - - if (!mShuttingDown && encryptedAnimation) { - static const std::vector<std::string> encryptedBootFiles = { - PRODUCT_ENCRYPTED_BOOTANIMATION_FILE, SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, - }; - if (findBootAnimationFileInternal(encryptedBootFiles)) { - return; - } - } - const bool playDarkAnim = android::base::GetIntProperty("ro.boot.theme", 0) == 1; static const std::vector<std::string> bootFiles = { APEX_BOOTANIMATION_FILE, playDarkAnim ? PRODUCT_BOOTANIMATION_DARK_FILE : PRODUCT_BOOTANIMATION_FILE, diff --git a/cmds/bootanimation/FORMAT.md b/cmds/bootanimation/FORMAT.md index 64814c8a25e2..988685e23443 100644 --- a/cmds/bootanimation/FORMAT.md +++ b/cmds/bootanimation/FORMAT.md @@ -4,7 +4,6 @@ The system selects a boot animation zipfile from the following locations, in order: - /system/media/bootanimation-encrypted.zip (if getprop("vold.decrypt") = '1') /system/media/bootanimation.zip /oem/media/bootanimation.zip diff --git a/cmds/idmap2/Android.bp b/cmds/idmap2/Android.bp index 6ef6845c75f2..18ec5a407b24 100644 --- a/cmds/idmap2/Android.bp +++ b/cmds/idmap2/Android.bp @@ -23,6 +23,7 @@ package { cc_defaults { name: "idmap2_defaults", + cpp_std: "gnu++2b", tidy: true, tidy_checks: [ "modernize-*", @@ -31,6 +32,7 @@ cc_defaults { "android-*", "misc-*", "readability-*", + "-readability-identifier-length", ], tidy_checks_as_errors: [ "modernize-*", @@ -54,7 +56,6 @@ cc_defaults { "-readability-convert-member-functions-to-static", "-readability-duplicate-include", "-readability-else-after-return", - "-readability-identifier-length", "-readability-named-parameter", "-readability-redundant-access-specifiers", "-readability-uppercase-literal-suffix", @@ -115,6 +116,7 @@ cc_library { "libidmap2/proto/*.proto", ], host_supported: true, + tidy: false, proto: { type: "lite", export_proto_headers: true, diff --git a/cmds/idmap2/tests/ResultTests.cpp b/cmds/idmap2/tests/ResultTests.cpp index f2f8854cec3a..f9c4fa3c798b 100644 --- a/cmds/idmap2/tests/ResultTests.cpp +++ b/cmds/idmap2/tests/ResultTests.cpp @@ -259,7 +259,8 @@ TEST(ResultTests, CascadeError) { } struct NoCopyContainer { - uint32_t value; // NOLINT(misc-non-private-member-variables-in-classes) + uint32_t value = 0; // NOLINT(misc-non-private-member-variables-in-classes) + NoCopyContainer() = default; NoCopyContainer(const NoCopyContainer&) = delete; NoCopyContainer& operator=(const NoCopyContainer&) = delete; }; @@ -268,7 +269,7 @@ Result<std::unique_ptr<NoCopyContainer>> CreateNoCopyContainer(bool succeed) { if (!succeed) { return Error("foo"); } - std::unique_ptr<NoCopyContainer> p(new NoCopyContainer{0U}); + std::unique_ptr<NoCopyContainer> p(new NoCopyContainer{}); p->value = 42U; return std::move(p); } diff --git a/cmds/telecom/src/com/android/commands/telecom/Telecom.java b/cmds/telecom/src/com/android/commands/telecom/Telecom.java index d464e266ac36..13c7946a033f 100644 --- a/cmds/telecom/src/com/android/commands/telecom/Telecom.java +++ b/cmds/telecom/src/com/android/commands/telecom/Telecom.java @@ -54,7 +54,7 @@ public final class Telecom extends BaseCommand { (new Telecom()).run(args); } - + private static final String CALLING_PACKAGE = Telecom.class.getPackageName(); private static final String COMMAND_SET_PHONE_ACCOUNT_ENABLED = "set-phone-account-enabled"; private static final String COMMAND_SET_PHONE_ACCOUNT_DISABLED = "set-phone-account-disabled"; private static final String COMMAND_REGISTER_PHONE_ACCOUNT = "register-phone-account"; @@ -297,7 +297,7 @@ public final class Telecom extends BaseCommand { final String label = nextArgRequired(); PhoneAccount account = PhoneAccount.builder(handle, label) .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER).build(); - mTelecomService.registerPhoneAccount(account); + mTelecomService.registerPhoneAccount(account, CALLING_PACKAGE); System.out.println("Success - " + handle + " registered."); } @@ -327,7 +327,7 @@ public final class Telecom extends BaseCommand { .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) .addSupportedUriScheme(PhoneAccount.SCHEME_VOICEMAIL) .build(); - mTelecomService.registerPhoneAccount(account); + mTelecomService.registerPhoneAccount(account, CALLING_PACKAGE); System.out.println("Success - " + handle + " registered."); } @@ -369,7 +369,7 @@ public final class Telecom extends BaseCommand { private void runUnregisterPhoneAccount() throws RemoteException { final PhoneAccountHandle handle = getPhoneAccountHandleFromArgs(); - mTelecomService.unregisterPhoneAccount(handle); + mTelecomService.unregisterPhoneAccount(handle, CALLING_PACKAGE); System.out.println("Success - " + handle + " unregistered."); } @@ -406,11 +406,11 @@ public final class Telecom extends BaseCommand { } private void runGetDefaultDialer() throws RemoteException { - System.out.println(mTelecomService.getDefaultDialerPackage()); + System.out.println(mTelecomService.getDefaultDialerPackage(CALLING_PACKAGE)); } private void runGetSystemDialer() throws RemoteException { - System.out.println(mTelecomService.getSystemDialerPackage()); + System.out.println(mTelecomService.getSystemDialerPackage(CALLING_PACKAGE)); } private void runWaitOnHandler() throws RemoteException { diff --git a/cmds/uinput/jni/com_android_commands_uinput_Device.cpp b/cmds/uinput/jni/com_android_commands_uinput_Device.cpp index 06fa2aac2c7e..3f4163dc54ec 100644 --- a/cmds/uinput/jni/com_android_commands_uinput_Device.cpp +++ b/cmds/uinput/jni/com_android_commands_uinput_Device.cpp @@ -99,6 +99,7 @@ JNIEnv* DeviceCallback::getJNIEnv() { std::unique_ptr<UinputDevice> UinputDevice::open(int32_t id, const char* name, int32_t vid, int32_t pid, uint16_t bus, uint32_t ffEffectsMax, + const char* port, std::unique_ptr<DeviceCallback> callback) { android::base::unique_fd fd(::open(UINPUT_PATH, O_RDWR | O_NONBLOCK | O_CLOEXEC)); if (!fd.ok()) { @@ -131,6 +132,9 @@ std::unique_ptr<UinputDevice> UinputDevice::open(int32_t id, const char* name, i return nullptr; } + // set the physical port. + ::ioctl(fd, UI_SET_PHYS, port); + if (::ioctl(fd, UI_DEV_CREATE) != 0) { ALOGE("Unable to create uinput device: %s.", strerror(errno)); return nullptr; @@ -240,17 +244,19 @@ std::vector<int32_t> toVector(JNIEnv* env, jintArray javaArray) { } static jlong openUinputDevice(JNIEnv* env, jclass /* clazz */, jstring rawName, jint id, jint vid, - jint pid, jint bus, jint ffEffectsMax, jobject callback) { + jint pid, jint bus, jint ffEffectsMax, jstring rawPort, + jobject callback) { ScopedUtfChars name(env, rawName); if (name.c_str() == nullptr) { return 0; } + ScopedUtfChars port(env, rawPort); std::unique_ptr<uinput::DeviceCallback> cb = std::make_unique<uinput::DeviceCallback>(env, callback); std::unique_ptr<uinput::UinputDevice> d = - uinput::UinputDevice::open(id, name.c_str(), vid, pid, bus, ffEffectsMax, + uinput::UinputDevice::open(id, name.c_str(), vid, pid, bus, ffEffectsMax, port.c_str(), std::move(cb)); return reinterpret_cast<jlong>(d.release()); } @@ -303,7 +309,7 @@ static void setAbsInfo(JNIEnv* env, jclass /* clazz */, jint handle, jint axisCo static JNINativeMethod sMethods[] = { {"nativeOpenUinputDevice", - "(Ljava/lang/String;IIIII" + "(Ljava/lang/String;IIIIILjava/lang/String;" "Lcom/android/commands/uinput/Device$DeviceCallback;)J", reinterpret_cast<void*>(openUinputDevice)}, {"nativeInjectEvent", "(JIII)V", reinterpret_cast<void*>(injectEvent)}, diff --git a/cmds/uinput/jni/com_android_commands_uinput_Device.h b/cmds/uinput/jni/com_android_commands_uinput_Device.h index 5a9a06cfb32e..6da3d7968ed0 100644 --- a/cmds/uinput/jni/com_android_commands_uinput_Device.h +++ b/cmds/uinput/jni/com_android_commands_uinput_Device.h @@ -48,6 +48,7 @@ class UinputDevice { public: static std::unique_ptr<UinputDevice> open(int32_t id, const char* name, int32_t vid, int32_t pid, uint16_t bus, uint32_t ff_effects_max, + const char* port, std::unique_ptr<DeviceCallback> callback); virtual ~UinputDevice(); diff --git a/cmds/uinput/src/com/android/commands/uinput/Device.java b/cmds/uinput/src/com/android/commands/uinput/Device.java index 62bee7b964bd..732b33d60c15 100644 --- a/cmds/uinput/src/com/android/commands/uinput/Device.java +++ b/cmds/uinput/src/com/android/commands/uinput/Device.java @@ -61,7 +61,7 @@ public class Device { } private static native long nativeOpenUinputDevice(String name, int id, int vid, int pid, - int bus, int ffEffectsMax, DeviceCallback callback); + int bus, int ffEffectsMax, String port, DeviceCallback callback); private static native void nativeCloseUinputDevice(long ptr); private static native void nativeInjectEvent(long ptr, int type, int code, int value); private static native void nativeConfigure(int handle, int code, int[] configs); @@ -69,7 +69,7 @@ public class Device { public Device(int id, String name, int vid, int pid, int bus, SparseArray<int[]> configuration, int ffEffectsMax, - SparseArray<InputAbsInfo> absInfo) { + SparseArray<InputAbsInfo> absInfo, String port) { mId = id; mThread = new HandlerThread("UinputDeviceHandler"); mThread.start(); @@ -88,6 +88,11 @@ public class Device { } else { args.arg1 = id + ":" + vid + ":" + pid; } + if (port != null) { + args.arg2 = port; + } else { + args.arg2 = "uinput:" + id + ":" + vid + ":" + pid; + } mHandler.obtainMessage(MSG_OPEN_UINPUT_DEVICE, args).sendToTarget(); mTimeToSend = SystemClock.uptimeMillis(); @@ -142,7 +147,7 @@ public class Device { case MSG_OPEN_UINPUT_DEVICE: SomeArgs args = (SomeArgs) msg.obj; mPtr = nativeOpenUinputDevice((String) args.arg1, args.argi1, args.argi2, - args.argi3, args.argi4, args.argi5, + args.argi3, args.argi4, args.argi5, (String) args.arg2, new DeviceCallback()); break; case MSG_INJECT_EVENT: diff --git a/cmds/uinput/src/com/android/commands/uinput/Event.java b/cmds/uinput/src/com/android/commands/uinput/Event.java index c4ba05054eda..9add310effaa 100644 --- a/cmds/uinput/src/com/android/commands/uinput/Event.java +++ b/cmds/uinput/src/com/android/commands/uinput/Event.java @@ -64,6 +64,7 @@ public class Event { private SparseArray<int[]> mConfiguration; private int mDuration; private int mFfEffectsMax = 0; + private String mInputport; private SparseArray<InputAbsInfo> mAbsInfo; public int getId() { @@ -110,6 +111,10 @@ public class Event { return mAbsInfo; } + public String getPort() { + return mInputport; + } + /** * Convert an event to String. */ @@ -124,6 +129,7 @@ public class Event { + ", configuration=" + mConfiguration + ", duration=" + mDuration + ", ff_effects_max=" + mFfEffectsMax + + ", port=" + mInputport + "}"; } @@ -178,6 +184,10 @@ public class Event { mEvent.mAbsInfo = absInfo; } + public void setInputport(String port) { + mEvent.mInputport = port; + } + public Event build() { if (mEvent.mId == -1) { throw new IllegalStateException("No event id"); @@ -262,6 +272,9 @@ public class Event { case "duration": eb.setDuration(readInt()); break; + case "port": + eb.setInputport(mReader.nextString()); + break; default: mReader.skipValue(); } diff --git a/cmds/uinput/src/com/android/commands/uinput/Uinput.java b/cmds/uinput/src/com/android/commands/uinput/Uinput.java index f7601a2f7c07..740578e878ac 100644 --- a/cmds/uinput/src/com/android/commands/uinput/Uinput.java +++ b/cmds/uinput/src/com/android/commands/uinput/Uinput.java @@ -123,7 +123,7 @@ public class Uinput { } int id = e.getId(); Device d = new Device(id, e.getName(), e.getVendorId(), e.getProductId(), e.getBus(), - e.getConfiguration(), e.getFfEffectsMax(), e.getAbsInfo()); + e.getConfiguration(), e.getFfEffectsMax(), e.getAbsInfo(), e.getPort()); mDevices.append(id, d); } diff --git a/core/api/current.txt b/core/api/current.txt index c8a43db2f9c2..9b72c4f1c67d 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -8996,6 +8996,7 @@ package android.companion { public final class CompanionDeviceManager { method @RequiresPermission(anyOf={android.Manifest.permission.REQUEST_COMPANION_PROFILE_WATCH, android.Manifest.permission.REQUEST_COMPANION_PROFILE_COMPUTER, android.Manifest.permission.REQUEST_COMPANION_PROFILE_APP_STREAMING, android.Manifest.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION}, conditional=true) public void associate(@NonNull android.companion.AssociationRequest, @NonNull android.companion.CompanionDeviceManager.Callback, @Nullable android.os.Handler); method @RequiresPermission(anyOf={android.Manifest.permission.REQUEST_COMPANION_PROFILE_WATCH, android.Manifest.permission.REQUEST_COMPANION_PROFILE_COMPUTER, android.Manifest.permission.REQUEST_COMPANION_PROFILE_APP_STREAMING, android.Manifest.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION}, conditional=true) public void associate(@NonNull android.companion.AssociationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.companion.CompanionDeviceManager.Callback); + method @Nullable public android.content.IntentSender buildPermissionTransferUserConsentIntent(int) throws android.companion.DeviceNotAssociatedException; method @Deprecated public void disassociate(@NonNull String); method public void disassociate(int); method @Deprecated @NonNull public java.util.List<java.lang.String> getAssociations(); @@ -9003,6 +9004,7 @@ package android.companion { method @Deprecated public boolean hasNotificationAccess(android.content.ComponentName); method public void requestNotificationAccess(android.content.ComponentName); method @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) public void startObservingDevicePresence(@NonNull String) throws android.companion.DeviceNotAssociatedException; + method public void startSystemDataTransfer(int) throws android.companion.DeviceNotAssociatedException; method @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) public void stopObservingDevicePresence(@NonNull String) throws android.companion.DeviceNotAssociatedException; field public static final String EXTRA_ASSOCIATION = "android.companion.extra.ASSOCIATION"; field @Deprecated public static final String EXTRA_DEVICE = "android.companion.extra.DEVICE"; @@ -9018,11 +9020,13 @@ package android.companion { public abstract class CompanionDeviceService extends android.app.Service { ctor public CompanionDeviceService(); + method @RequiresPermission(android.Manifest.permission.DELIVER_COMPANION_MESSAGES) public final void dispatchMessageToSystem(int, int, @NonNull byte[]) throws android.companion.DeviceNotAssociatedException; method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent); method @Deprecated @MainThread public void onDeviceAppeared(@NonNull String); method @MainThread public void onDeviceAppeared(@NonNull android.companion.AssociationInfo); method @Deprecated @MainThread public void onDeviceDisappeared(@NonNull String); method @MainThread public void onDeviceDisappeared(@NonNull android.companion.AssociationInfo); + method public void onMessageDispatchedFromSystem(int, int, @NonNull byte[]); field public static final String SERVICE_INTERFACE = "android.companion.CompanionDeviceService"; } @@ -18526,7 +18530,7 @@ package android.hardware.fingerprint { package android.hardware.input { public final class InputManager { - method public android.view.InputDevice getInputDevice(int); + method @Nullable public android.view.InputDevice getInputDevice(int); method public int[] getInputDeviceIds(); method @FloatRange(from=0, to=1) public float getMaximumObscuringOpacityForTouch(); method public void registerInputDeviceListener(android.hardware.input.InputManager.InputDeviceListener, android.os.Handler); @@ -20081,14 +20085,14 @@ package android.media { method @Deprecated public int getVibrateSetting(int); method @Deprecated public boolean isBluetoothA2dpOn(); method public boolean isBluetoothScoAvailableOffCall(); - method public boolean isBluetoothScoOn(); + method @Deprecated public boolean isBluetoothScoOn(); method public boolean isCallScreeningModeSupported(); method public static boolean isHapticPlaybackSupported(); method public boolean isMicrophoneMute(); method public boolean isMusicActive(); method public static boolean isOffloadedPlaybackSupported(@NonNull android.media.AudioFormat, @NonNull android.media.AudioAttributes); method public boolean isRampingRingerEnabled(); - method public boolean isSpeakerphoneOn(); + method @Deprecated public boolean isSpeakerphoneOn(); method public boolean isStreamMute(int); method public boolean isSurroundFormatEnabled(int); method public boolean isVolumeFixed(); @@ -20117,7 +20121,7 @@ package android.media { method public void setParameters(String); method public void setRingerMode(int); method @Deprecated public void setRouting(int, int, int); - method public void setSpeakerphoneOn(boolean); + method @Deprecated public void setSpeakerphoneOn(boolean); method @Deprecated public void setStreamMute(int, boolean); method @Deprecated public void setStreamSolo(int, boolean); method public void setStreamVolume(int, int, int); @@ -20125,8 +20129,8 @@ package android.media { method @Deprecated public void setVibrateSetting(int, int); method @Deprecated public void setWiredHeadsetOn(boolean); method @Deprecated public boolean shouldVibrate(int); - method public void startBluetoothSco(); - method public void stopBluetoothSco(); + method @Deprecated public void startBluetoothSco(); + method @Deprecated public void stopBluetoothSco(); method public void unloadSoundEffects(); method public void unregisterAudioDeviceCallback(android.media.AudioDeviceCallback); method public void unregisterAudioPlaybackCallback(@NonNull android.media.AudioManager.AudioPlaybackCallback); @@ -30978,6 +30982,7 @@ package android.os { field public static final int S = 31; // 0x1f field public static final int S_V2 = 32; // 0x20 field public static final int TIRAMISU = 33; // 0x21 + field public static final int UPSIDE_DOWN_CAKE = 10000; // 0x2710 } public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable { @@ -32341,6 +32346,9 @@ package android.os { method public static android.os.VibrationEffect createWaveform(long[], int[], int); method public int describeContents(); method @NonNull public static android.os.VibrationEffect.Composition startComposition(); + method @NonNull public static android.os.VibrationEffect.WaveformBuilder startWaveform(); + method @NonNull public static android.os.VibrationEffect.WaveformBuilder startWaveform(@NonNull android.os.VibrationEffect.VibrationParameter); + method @NonNull public static android.os.VibrationEffect.WaveformBuilder startWaveform(@NonNull android.os.VibrationEffect.VibrationParameter, @NonNull android.os.VibrationEffect.VibrationParameter); field @NonNull public static final android.os.Parcelable.Creator<android.os.VibrationEffect> CREATOR; field public static final int DEFAULT_AMPLITUDE = -1; // 0xffffffff field public static final int EFFECT_CLICK = 0; // 0x0 @@ -32350,10 +32358,13 @@ package android.os { } public static final class VibrationEffect.Composition { + method @NonNull public android.os.VibrationEffect.Composition addEffect(@NonNull android.os.VibrationEffect); + method @NonNull public android.os.VibrationEffect.Composition addOffDuration(@NonNull java.time.Duration); method @NonNull public android.os.VibrationEffect.Composition addPrimitive(int); method @NonNull public android.os.VibrationEffect.Composition addPrimitive(int, @FloatRange(from=0.0f, to=1.0f) float); method @NonNull public android.os.VibrationEffect.Composition addPrimitive(int, @FloatRange(from=0.0f, to=1.0f) float, @IntRange(from=0) int); method @NonNull public android.os.VibrationEffect compose(); + method @NonNull public android.os.VibrationEffect.Composition repeatEffectIndefinitely(@NonNull android.os.VibrationEffect); field public static final int PRIMITIVE_CLICK = 1; // 0x1 field public static final int PRIMITIVE_LOW_TICK = 8; // 0x8 field public static final int PRIMITIVE_QUICK_FALL = 6; // 0x6 @@ -32364,15 +32375,34 @@ package android.os { field public static final int PRIMITIVE_TICK = 7; // 0x7 } + public static final class VibrationEffect.Composition.UnreachableAfterRepeatingIndefinitelyException extends java.lang.IllegalStateException { + } + + public static class VibrationEffect.VibrationParameter { + method @NonNull public static android.os.VibrationEffect.VibrationParameter targetAmplitude(@FloatRange(from=0, to=1) float); + method @NonNull public static android.os.VibrationEffect.VibrationParameter targetFrequency(@FloatRange(from=1) float); + } + + public static final class VibrationEffect.WaveformBuilder { + method @NonNull public android.os.VibrationEffect.WaveformBuilder addSustain(@NonNull java.time.Duration); + method @NonNull public android.os.VibrationEffect.WaveformBuilder addTransition(@NonNull java.time.Duration, @NonNull android.os.VibrationEffect.VibrationParameter); + method @NonNull public android.os.VibrationEffect.WaveformBuilder addTransition(@NonNull java.time.Duration, @NonNull android.os.VibrationEffect.VibrationParameter, @NonNull android.os.VibrationEffect.VibrationParameter); + method @NonNull public android.os.VibrationEffect build(); + } + public abstract class Vibrator { method public final int areAllEffectsSupported(@NonNull int...); method public final boolean areAllPrimitivesSupported(@NonNull int...); method @NonNull public int[] areEffectsSupported(@NonNull int...); method @NonNull public boolean[] arePrimitivesSupported(@NonNull int...); method @RequiresPermission(android.Manifest.permission.VIBRATE) public abstract void cancel(); + method @Nullable public android.os.vibrator.VibratorFrequencyProfile getFrequencyProfile(); method public int getId(); method @NonNull public int[] getPrimitiveDurations(@NonNull int...); + method public float getQFactor(); + method public float getResonantFrequency(); method public abstract boolean hasAmplitudeControl(); + method public boolean hasFrequencyControl(); method public abstract boolean hasVibrator(); method @Deprecated @RequiresPermission(android.Manifest.permission.VIBRATE) public void vibrate(long); method @Deprecated @RequiresPermission(android.Manifest.permission.VIBRATE) public void vibrate(long, android.media.AudioAttributes); @@ -32700,6 +32730,17 @@ package android.os.strictmode { } +package android.os.vibrator { + + public final class VibratorFrequencyProfile { + method public float getMaxAmplitudeMeasurementInterval(); + method @FloatRange(from=0, to=1) @NonNull public float[] getMaxAmplitudeMeasurements(); + method public float getMaxFrequency(); + method public float getMinFrequency(); + } + +} + package android.preference { @Deprecated public class CheckBoxPreference extends android.preference.TwoStatePreference { @@ -39029,6 +39070,7 @@ package android.service.notification { field public static final int REASON_GROUP_SUMMARY_CANCELED = 12; // 0xc field public static final int REASON_LISTENER_CANCEL = 10; // 0xa field public static final int REASON_LISTENER_CANCEL_ALL = 11; // 0xb + field public static final int REASON_LOCKDOWN = 23; // 0x17 field public static final int REASON_PACKAGE_BANNED = 7; // 0x7 field public static final int REASON_PACKAGE_CHANGED = 5; // 0x5 field public static final int REASON_PACKAGE_SUSPENDED = 14; // 0xe @@ -48126,7 +48168,7 @@ package android.view { method @NonNull public android.hardware.BatteryState getBatteryState(); method public int getControllerNumber(); method public String getDescriptor(); - method public static android.view.InputDevice getDevice(int); + method @Nullable public static android.view.InputDevice getDevice(int); method public static int[] getDeviceIds(); method public int getId(); method public android.view.KeyCharacterMap getKeyCharacterMap(); @@ -52505,6 +52547,7 @@ package android.view.autofill { public final class AutofillManager { method public void cancel(); + method public void clearAutofillRequestCallback(); method public void commit(); method public void disableAutofillServices(); method @Nullable public android.content.ComponentName getAutofillServiceComponentName(); @@ -52530,6 +52573,7 @@ package android.view.autofill { method public void registerCallback(@Nullable android.view.autofill.AutofillManager.AutofillCallback); method public void requestAutofill(@NonNull android.view.View); method public void requestAutofill(@NonNull android.view.View, int, @NonNull android.graphics.Rect); + method public void setAutofillRequestCallback(@NonNull java.util.concurrent.Executor, @NonNull android.view.autofill.AutofillRequestCallback); method public void setUserData(@Nullable android.service.autofill.UserData); method public boolean showAutofillDialog(@NonNull android.view.View); method public boolean showAutofillDialog(@NonNull android.view.View, int); @@ -52550,6 +52594,10 @@ package android.view.autofill { field public static final int EVENT_INPUT_UNAVAILABLE = 3; // 0x3 } + public interface AutofillRequestCallback { + method public void onFillRequest(@Nullable android.view.inputmethod.InlineSuggestionsRequest, @NonNull android.os.CancellationSignal, @NonNull android.service.autofill.FillCallback); + } + public final class AutofillValue implements android.os.Parcelable { method public int describeContents(); method public static android.view.autofill.AutofillValue forDate(long); @@ -52937,10 +52985,12 @@ package android.view.inputmethod { ctor public InlineSuggestionsRequest.Builder(@NonNull java.util.List<android.widget.inline.InlinePresentationSpec>); method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder addInlinePresentationSpecs(@NonNull android.widget.inline.InlinePresentationSpec); method @NonNull public android.view.inputmethod.InlineSuggestionsRequest build(); + method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setClientSupported(boolean); method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setExtras(@NonNull android.os.Bundle); method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setInlinePresentationSpecs(@NonNull java.util.List<android.widget.inline.InlinePresentationSpec>); method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setInlineTooltipPresentationSpec(@NonNull android.widget.inline.InlinePresentationSpec); method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setMaxSuggestionCount(int); + method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setServiceSupported(boolean); method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setSupportedLocales(@NonNull android.os.LocaleList); } diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt index b9522163b5d0..e81d7f1a9fce 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -2,6 +2,7 @@ package android { public static final class Manifest.permission { + field public static final String BLUETOOTH_STACK = "android.permission.BLUETOOTH_STACK"; field public static final String CONTROL_AUTOMOTIVE_GNSS = "android.permission.CONTROL_AUTOMOTIVE_GNSS"; field public static final String GET_INTENT_SENDER_INTENT = "android.permission.GET_INTENT_SENDER_INTENT"; field public static final String MAKE_UID_VISIBLE = "android.permission.MAKE_UID_VISIBLE"; @@ -156,12 +157,12 @@ package android.media { method public void adjustSuggestedStreamVolumeForUid(int, int, int, @NonNull String, int, int, int); method @NonNull public java.util.List<android.bluetooth.BluetoothCodecConfig> getHwOffloadFormatsSupportedForA2dp(); method @NonNull public java.util.List<android.bluetooth.BluetoothLeAudioCodecConfig> getHwOffloadFormatsSupportedForLeAudio(); - method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void handleBluetoothActiveDeviceChanged(@Nullable android.bluetooth.BluetoothDevice, @Nullable android.bluetooth.BluetoothDevice, @NonNull android.media.BluetoothProfileConnectionInfo); - method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setA2dpSuspended(boolean); - method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setBluetoothHeadsetProperties(@NonNull String, boolean, boolean); - method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setHfpEnabled(boolean); - method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setHfpSamplingRate(int); - method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setHfpVolume(int); + method @RequiresPermission(android.Manifest.permission.BLUETOOTH_STACK) public void handleBluetoothActiveDeviceChanged(@Nullable android.bluetooth.BluetoothDevice, @Nullable android.bluetooth.BluetoothDevice, @NonNull android.media.BluetoothProfileConnectionInfo); + method @RequiresPermission(android.Manifest.permission.BLUETOOTH_STACK) public void setA2dpSuspended(boolean); + method @RequiresPermission(android.Manifest.permission.BLUETOOTH_STACK) public void setBluetoothHeadsetProperties(@NonNull String, boolean, boolean); + method @RequiresPermission(android.Manifest.permission.BLUETOOTH_STACK) public void setHfpEnabled(boolean); + method @RequiresPermission(android.Manifest.permission.BLUETOOTH_STACK) public void setHfpSamplingRate(int); + method @RequiresPermission(android.Manifest.permission.BLUETOOTH_STACK) public void setHfpVolume(int); method public void setStreamVolumeForUid(int, int, int, @NonNull String, int, int, int); field public static final int FLAG_FROM_KEY = 4096; // 0x1000 } diff --git a/core/api/system-current.txt b/core/api/system-current.txt index ec4ad8b704c3..356998527801 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -199,6 +199,7 @@ package android { field public static final String MANAGE_WEAK_ESCROW_TOKEN = "android.permission.MANAGE_WEAK_ESCROW_TOKEN"; field public static final String MANAGE_WIFI_COUNTRY_CODE = "android.permission.MANAGE_WIFI_COUNTRY_CODE"; field public static final String MARK_DEVICE_ORGANIZATION_OWNED = "android.permission.MARK_DEVICE_ORGANIZATION_OWNED"; + field public static final String MEDIA_RESOURCE_OVERRIDE_PID = "android.permission.MEDIA_RESOURCE_OVERRIDE_PID"; field public static final String MODIFY_APPWIDGET_BIND_PERMISSIONS = "android.permission.MODIFY_APPWIDGET_BIND_PERMISSIONS"; field public static final String MODIFY_AUDIO_ROUTING = "android.permission.MODIFY_AUDIO_ROUTING"; field public static final String MODIFY_CELL_BROADCASTS = "android.permission.MODIFY_CELL_BROADCASTS"; @@ -1050,7 +1051,7 @@ package android.app { public class WallpaperManager { method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public void clearWallpaper(int, int); - method @RequiresPermission(android.Manifest.permission.SET_WALLPAPER_DIM_AMOUNT) public float getWallpaperDimAmount(); + method @FloatRange(from=0.0f, to=1.0f) @RequiresPermission(android.Manifest.permission.SET_WALLPAPER_DIM_AMOUNT) public float getWallpaperDimAmount(); method public void setDisplayOffset(android.os.IBinder, int, int); method @RequiresPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT) public boolean setWallpaperComponent(android.content.ComponentName); method @RequiresPermission(android.Manifest.permission.SET_WALLPAPER_DIM_AMOUNT) public void setWallpaperDimAmount(@FloatRange(from=0.0f, to=1.0f) float); @@ -6334,7 +6335,7 @@ package android.media { } public final class MediaCodec { - method @NonNull @RequiresPermission("android.permission.MEDIA_RESOURCE_OVERRIDE_PID") public static android.media.MediaCodec createByCodecNameForClient(@NonNull String, int, int) throws java.io.IOException; + method @NonNull @RequiresPermission(android.Manifest.permission.MEDIA_RESOURCE_OVERRIDE_PID) public static android.media.MediaCodec createByCodecNameForClient(@NonNull String, int, int) throws java.io.IOException; } public class MediaPlayer implements android.media.AudioRouting android.media.VolumeAutomation { @@ -11873,19 +11874,20 @@ package android.service.trust { package android.service.voice { public class AlwaysOnHotwordDetector implements android.service.voice.HotwordDetector { - method @Nullable public android.content.Intent createEnrollIntent(); - method @Nullable public android.content.Intent createReEnrollIntent(); - method @Nullable public android.content.Intent createUnEnrollIntent(); - method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public int getParameter(int); + method @Nullable public android.content.Intent createEnrollIntent() throws android.service.voice.HotwordDetector.IllegalDetectorStateException; + method @Nullable public android.content.Intent createReEnrollIntent() throws android.service.voice.HotwordDetector.IllegalDetectorStateException; + method @Nullable public android.content.Intent createUnEnrollIntent() throws android.service.voice.HotwordDetector.IllegalDetectorStateException; + method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public int getParameter(int) throws android.service.voice.HotwordDetector.IllegalDetectorStateException; method public int getSupportedAudioCapabilities(); - method public int getSupportedRecognitionModes(); - method @Nullable @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public android.service.voice.AlwaysOnHotwordDetector.ModelParamRange queryParameter(int); - method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public int setParameter(int, int); - method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public boolean startRecognition(int); - method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public boolean startRecognition(); - method public boolean startRecognition(@NonNull android.os.ParcelFileDescriptor, @NonNull android.media.AudioFormat, @Nullable android.os.PersistableBundle); - method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public boolean stopRecognition(); - method public final void updateState(@Nullable android.os.PersistableBundle, @Nullable android.os.SharedMemory); + method public int getSupportedRecognitionModes() throws android.service.voice.HotwordDetector.IllegalDetectorStateException; + method @Nullable @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public android.service.voice.AlwaysOnHotwordDetector.ModelParamRange queryParameter(int) throws android.service.voice.HotwordDetector.IllegalDetectorStateException; + method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public int setParameter(int, int) throws android.service.voice.HotwordDetector.IllegalDetectorStateException; + method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public boolean startRecognition(int, @NonNull byte[]) throws android.service.voice.HotwordDetector.IllegalDetectorStateException; + method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public boolean startRecognition(int) throws android.service.voice.HotwordDetector.IllegalDetectorStateException; + method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public boolean startRecognition() throws android.service.voice.HotwordDetector.IllegalDetectorStateException; + method public boolean startRecognition(@NonNull android.os.ParcelFileDescriptor, @NonNull android.media.AudioFormat, @Nullable android.os.PersistableBundle) throws android.service.voice.HotwordDetector.IllegalDetectorStateException; + method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public boolean stopRecognition() throws android.service.voice.HotwordDetector.IllegalDetectorStateException; + method public final void updateState(@Nullable android.os.PersistableBundle, @Nullable android.os.SharedMemory) throws android.service.voice.HotwordDetector.IllegalDetectorStateException; field public static final int AUDIO_CAPABILITY_ECHO_CANCELLATION = 1; // 0x1 field public static final int AUDIO_CAPABILITY_NOISE_SUPPRESSION = 2; // 0x2 field public static final int MODEL_PARAM_THRESHOLD_FACTOR = 0; // 0x0 @@ -11992,10 +11994,10 @@ package android.service.voice { public interface HotwordDetector { method public default void destroy(); - method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public boolean startRecognition(); - method public boolean startRecognition(@NonNull android.os.ParcelFileDescriptor, @NonNull android.media.AudioFormat, @Nullable android.os.PersistableBundle); - method public boolean stopRecognition(); - method public void updateState(@Nullable android.os.PersistableBundle, @Nullable android.os.SharedMemory); + method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public boolean startRecognition() throws android.service.voice.HotwordDetector.IllegalDetectorStateException; + method public boolean startRecognition(@NonNull android.os.ParcelFileDescriptor, @NonNull android.media.AudioFormat, @Nullable android.os.PersistableBundle) throws android.service.voice.HotwordDetector.IllegalDetectorStateException; + method public boolean stopRecognition() throws android.service.voice.HotwordDetector.IllegalDetectorStateException; + method public void updateState(@Nullable android.os.PersistableBundle, @Nullable android.os.SharedMemory) throws android.service.voice.HotwordDetector.IllegalDetectorStateException; } public static interface HotwordDetector.Callback { @@ -12008,6 +12010,9 @@ package android.service.voice { method public void onRejected(@NonNull android.service.voice.HotwordRejectedResult); } + public static class HotwordDetector.IllegalDetectorStateException extends android.util.AndroidException { + } + public final class HotwordRejectedResult implements android.os.Parcelable { method public int describeContents(); method public int getConfidenceLevel(); diff --git a/core/api/system-lint-baseline.txt b/core/api/system-lint-baseline.txt index 1b45e88584fe..db375d42f0b1 100644 --- a/core/api/system-lint-baseline.txt +++ b/core/api/system-lint-baseline.txt @@ -99,15 +99,6 @@ ProtectedMember: android.service.notification.NotificationAssistantService#attac -RethrowRemoteException: android.app.WallpaperManager#getWallpaperDimAmount(): - Methods calling system APIs should rethrow `RemoteException` as `RuntimeException` (but do not list it in the throws clause) -RethrowRemoteException: android.app.WallpaperManager#getWallpaperDimmingAmount(): - Methods calling system APIs should rethrow `RemoteException` as `RuntimeException` (but do not list it in the throws clause) -RethrowRemoteException: android.app.WallpaperManager#setWallpaperDimAmount(float): - Methods calling system APIs should rethrow `RemoteException` as `RuntimeException` (but do not list it in the throws clause) -RethrowRemoteException: android.app.WallpaperManager#setWallpaperDimmingAmount(float): - Methods calling system APIs should rethrow `RemoteException` as `RuntimeException` (but do not list it in the throws clause) - SamShouldBeLast: android.accounts.AccountManager#addAccount(String, String, String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler): diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 167cd344a2c9..e0aed61a0ea6 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -1250,10 +1250,12 @@ package android.hardware.input { } public final class InputManager { + method public void addUniqueIdAssociation(@NonNull String, @NonNull String); method public int getBlockUntrustedTouchesMode(@NonNull android.content.Context); method @Nullable public String getCurrentKeyboardLayoutForInputDevice(@NonNull android.hardware.input.InputDeviceIdentifier); method @NonNull public java.util.List<java.lang.String> getKeyboardLayoutDescriptorsForInputDevice(@NonNull android.view.InputDevice); method @RequiresPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT) public void removeKeyboardLayoutForInputDevice(@NonNull android.hardware.input.InputDeviceIdentifier, @NonNull String); + method public void removeUniqueIdAssociation(@NonNull String); method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setBlockUntrustedTouchesMode(@NonNull android.content.Context, int); method @RequiresPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT) public void setCurrentKeyboardLayoutForInputDevice(@NonNull android.hardware.input.InputDeviceIdentifier, @NonNull String); method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setMaximumObscuringOpacityForTouch(@FloatRange(from=0, to=1) float); @@ -1857,7 +1859,6 @@ package android.os { method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public String getUserType(); method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public java.util.List<android.content.pm.UserInfo> getUsers(boolean, boolean, boolean); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public boolean hasBaseUserRestriction(@NonNull String, @NonNull android.os.UserHandle); - method public static boolean isGuestUserEphemeral(); method public static boolean isSplitSystemUser(); method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.content.pm.UserInfo preCreateUser(@NonNull String) throws android.os.UserManager.UserOperationException; } @@ -1871,9 +1872,6 @@ package android.os { method public static android.os.VibrationEffect get(int, boolean); method @Nullable public static android.os.VibrationEffect get(android.net.Uri, android.content.Context); method public abstract long getDuration(); - method @NonNull public static android.os.VibrationEffect.WaveformBuilder startWaveform(); - method @NonNull public static android.os.VibrationEffect.WaveformBuilder startWaveform(@NonNull android.os.VibrationEffect.VibrationParameter); - method @NonNull public static android.os.VibrationEffect.WaveformBuilder startWaveform(@NonNull android.os.VibrationEffect.VibrationParameter, @NonNull android.os.VibrationEffect.VibrationParameter); field public static final int EFFECT_POP = 4; // 0x4 field public static final int EFFECT_STRENGTH_LIGHT = 0; // 0x0 field public static final int EFFECT_STRENGTH_MEDIUM = 1; // 0x1 @@ -1891,33 +1889,8 @@ package android.os { field @NonNull public static final android.os.Parcelable.Creator<android.os.VibrationEffect.Composed> CREATOR; } - public static final class VibrationEffect.Composition { - method @NonNull public android.os.VibrationEffect.Composition addEffect(@NonNull android.os.VibrationEffect); - method @NonNull public android.os.VibrationEffect.Composition addOffDuration(@NonNull java.time.Duration); - method @NonNull public android.os.VibrationEffect.Composition repeatEffectIndefinitely(@NonNull android.os.VibrationEffect); - } - - public static final class VibrationEffect.Composition.UnreachableAfterRepeatingIndefinitelyException extends java.lang.IllegalStateException { - } - - public static class VibrationEffect.VibrationParameter { - method @NonNull public static android.os.VibrationEffect.VibrationParameter targetAmplitude(@FloatRange(from=0, to=1) float); - method @NonNull public static android.os.VibrationEffect.VibrationParameter targetFrequency(@FloatRange(from=1) float); - } - - public static final class VibrationEffect.WaveformBuilder { - method @NonNull public android.os.VibrationEffect.WaveformBuilder addSustain(@NonNull java.time.Duration); - method @NonNull public android.os.VibrationEffect.WaveformBuilder addTransition(@NonNull java.time.Duration, @NonNull android.os.VibrationEffect.VibrationParameter); - method @NonNull public android.os.VibrationEffect.WaveformBuilder addTransition(@NonNull java.time.Duration, @NonNull android.os.VibrationEffect.VibrationParameter, @NonNull android.os.VibrationEffect.VibrationParameter); - method @NonNull public android.os.VibrationEffect build(); - } - public abstract class Vibrator { method public int getDefaultVibrationIntensity(int); - method @Nullable public android.os.vibrator.VibratorFrequencyProfile getFrequencyProfile(); - method public float getQFactor(); - method public float getResonantFrequency(); - method public boolean hasFrequencyControl(); field public static final int VIBRATION_INTENSITY_HIGH = 3; // 0x3 field public static final int VIBRATION_INTENSITY_LOW = 1; // 0x1 field public static final int VIBRATION_INTENSITY_MEDIUM = 2; // 0x2 @@ -2102,13 +2075,6 @@ package android.os.vibrator { field @NonNull public static final android.os.Parcelable.Creator<android.os.vibrator.VibrationEffectSegment> CREATOR; } - public final class VibratorFrequencyProfile { - method public float getMaxAmplitudeMeasurementInterval(); - method @FloatRange(from=0, to=1) @NonNull public float[] getMaxAmplitudeMeasurements(); - method public float getMaxFrequency(); - method public float getMinFrequency(); - } - } package android.permission { @@ -2465,6 +2431,8 @@ package android.service.quicksettings { package android.service.voice { public class AlwaysOnHotwordDetector implements android.service.voice.HotwordDetector { + method public void overrideAvailability(int); + method public void resetAvailability(); method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public void triggerHardwareRecognitionEventForTest(int, int, boolean, int, int, int, boolean, @NonNull android.media.AudioFormat, @Nullable byte[], @NonNull java.util.List<android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionExtra>); } @@ -2824,6 +2792,7 @@ package android.view { method @NonNull public android.graphics.ColorSpace[] getSupportedWideColorGamut(); method @Nullable public android.view.Display.Mode getSystemPreferredDisplayMode(); method public int getType(); + method @Nullable public String getUniqueId(); method @Nullable public android.view.Display.Mode getUserPreferredDisplayMode(); method public boolean hasAccess(int); method @RequiresPermission(android.Manifest.permission.MODIFY_USER_PREFERRED_DISPLAY_MODE) public void setUserPreferredDisplayMode(@NonNull android.view.Display.Mode); diff --git a/core/java/android/accounts/Account.java b/core/java/android/accounts/Account.java index e6cdcc0ee742..0d6a07938e95 100644 --- a/core/java/android/accounts/Account.java +++ b/core/java/android/accounts/Account.java @@ -31,7 +31,6 @@ import android.util.Log; import com.android.internal.annotations.GuardedBy; -import java.util.Objects; import java.util.Set; /** @@ -87,12 +86,6 @@ public class Account implements Parcelable { if (TextUtils.isEmpty(type)) { throw new IllegalArgumentException("the type must not be empty: " + type); } - if (name.length() > 200) { - throw new IllegalArgumentException("account name is longer than 200 characters"); - } - if (type.length() > 200) { - throw new IllegalArgumentException("account type is longer than 200 characters"); - } this.name = name; this.type = type; this.accessId = accessId; diff --git a/core/java/android/app/IWallpaperManager.aidl b/core/java/android/app/IWallpaperManager.aidl index 28c273ec50a6..167de463ad17 100644 --- a/core/java/android/app/IWallpaperManager.aidl +++ b/core/java/android/app/IWallpaperManager.aidl @@ -211,6 +211,7 @@ interface IWallpaperManager { * * @hide */ + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.SET_WALLPAPER_DIM_AMOUNT)") oneway void setWallpaperDimAmount(float dimAmount); /** @@ -219,6 +220,7 @@ interface IWallpaperManager { * * @hide */ + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.SET_WALLPAPER_DIM_AMOUNT)") float getWallpaperDimAmount(); /** diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java index 5d6e2bda0b83..7964ae904392 100644 --- a/core/java/android/app/UiAutomationConnection.java +++ b/core/java/android/app/UiAutomationConnection.java @@ -431,8 +431,7 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub { writeTo.write(buffer, 0, readByteCount); writeTo.flush(); } - } catch (IOException ioe) { - Log.w(TAG, "Error while reading/writing to streams"); + } catch (IOException ignored) { } finally { IoUtils.closeQuietly(readFrom); IoUtils.closeQuietly(writeTo); diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index e022ca306674..ea80369983a5 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -67,6 +67,7 @@ import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.StrictMode; import android.os.SystemProperties; +import android.service.wallpaper.WallpaperService; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; @@ -558,26 +559,23 @@ public class WallpaperManager { } mCachedWallpaper = null; mCachedWallpaperUserId = 0; - } - try { - Bitmap currentWallpaper = getCurrentWallpaperLocked( - context, userId, hardware, cmProxy); - if (currentWallpaper != null) { - synchronized (this) { - mCachedWallpaper = currentWallpaper; - mCachedWallpaperUserId = userId; - return mCachedWallpaper; + try { + mCachedWallpaper = getCurrentWallpaperLocked( + context, userId, hardware, cmProxy); + mCachedWallpaperUserId = userId; + } catch (OutOfMemoryError e) { + Log.w(TAG, "Out of memory loading the current wallpaper: " + e); + } catch (SecurityException e) { + if (context.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.O_MR1) { + Log.w(TAG, "No permission to access wallpaper, suppressing" + + " exception to avoid crashing legacy app."); + } else { + // Post-O apps really most sincerely need the permission. + throw e; } } - } catch (OutOfMemoryError e) { - Log.w(TAG, "Out of memory loading the current wallpaper: " + e); - } catch (SecurityException e) { - if (context.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.O_MR1) { - Log.w(TAG, "No permission to access wallpaper, suppressing" - + " exception to avoid crashing legacy app."); - } else { - // Post-O apps really most sincerely need the permission. - throw e; + if (mCachedWallpaper != null) { + return mCachedWallpaper; } } if (returnDefault) { @@ -2025,7 +2023,7 @@ public class WallpaperManager { */ @SystemApi @RequiresPermission(android.Manifest.permission.SET_WALLPAPER_DIM_AMOUNT) - public float getWallpaperDimAmount() { + public @FloatRange (from = 0f, to = 1f) float getWallpaperDimAmount() { if (sGlobals.mService == null) { Log.w(TAG, "WallpaperService not running"); throw new RuntimeException(new DeadSystemException()); @@ -2474,7 +2472,7 @@ public class WallpaperManager { * * @param colors Wallpaper color info, {@code null} when not available. * @param which A combination of {@link #FLAG_LOCK} and {@link #FLAG_SYSTEM} - * @see android.service.wallpaper.WallpaperService.Engine#onComputeColors() + * @see WallpaperService.Engine#onComputeColors() */ void onColorsChanged(@Nullable WallpaperColors colors, int which); @@ -2486,7 +2484,7 @@ public class WallpaperManager { * @param colors Wallpaper color info, {@code null} when not available. * @param which A combination of {@link #FLAG_LOCK} and {@link #FLAG_SYSTEM} * @param userId Owner of the wallpaper - * @see android.service.wallpaper.WallpaperService.Engine#onComputeColors() + * @see WallpaperService.Engine#onComputeColors() * @hide */ default void onColorsChanged(@Nullable WallpaperColors colors, int which, int userId) { diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index d11b23cc871b..26b9bc82cd38 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -148,8 +148,8 @@ import java.util.function.Consumer; * <p><b>Note: </b>on * {@link android.content.pm.PackageManager#FEATURE_AUTOMOTIVE automotive builds}, some methods can * throw an {@link UnsafeStateException} exception (for example, if the vehicle is moving), so - * callers running on automotive builds should wrap every method call under the methods provided by - * {@code android.car.admin.CarDevicePolicyManager}. + * callers running on automotive builds should always check for that exception, otherwise they + * might crash. * * <div class="special reference"> * <h3>Developer Guides</h3> diff --git a/core/java/android/app/admin/EnterprisePlatformSecurity_OWNERS b/core/java/android/app/admin/EnterprisePlatformSecurity_OWNERS index f5604347065e..0ec825371515 100644 --- a/core/java/android/app/admin/EnterprisePlatformSecurity_OWNERS +++ b/core/java/android/app/admin/EnterprisePlatformSecurity_OWNERS @@ -1,4 +1,5 @@ rubinxu@google.com acjohnston@google.com pgrafov@google.com +ayushsha@google.com alexkershaw@google.com #{LAST_RESORT_SUGGESTION}
\ No newline at end of file diff --git a/core/java/android/app/admin/WorkDeviceExperience_OWNERS b/core/java/android/app/admin/WorkDeviceExperience_OWNERS index dcacaa25a236..7c90feb1871f 100644 --- a/core/java/android/app/admin/WorkDeviceExperience_OWNERS +++ b/core/java/android/app/admin/WorkDeviceExperience_OWNERS @@ -2,4 +2,5 @@ work-device-experience+reviews@google.com scottjonathan@google.com arangelov@google.com kholoudm@google.com +eliselliott@google.com alexkershaw@google.com #{LAST_RESORT_SUGGESTION}
\ No newline at end of file diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java index 67f631f98f0b..88a7c0f910d3 100644 --- a/core/java/android/app/backup/BackupManager.java +++ b/core/java/android/app/backup/BackupManager.java @@ -246,6 +246,9 @@ public class BackupManager { * new changes to its data. A backup operation using your application's * {@link android.app.backup.BackupAgent} subclass will be scheduled when you * call this method. + * + * <p> + * Note: This only works if your application is performing Key/Value backups. */ public void dataChanged() { checkServiceBinder(); @@ -268,6 +271,8 @@ public class BackupManager { * as the caller. * * @param packageName The package name identifying the application to back up. + * <p> + * Note: Only works for packages performing Key/Value backups. */ public static void dataChanged(String packageName) { checkServiceBinder(); diff --git a/core/java/android/app/slice/ISliceManager.aidl b/core/java/android/app/slice/ISliceManager.aidl index 6f73d02caa12..f31e2bce84b4 100644 --- a/core/java/android/app/slice/ISliceManager.aidl +++ b/core/java/android/app/slice/ISliceManager.aidl @@ -33,7 +33,7 @@ interface ISliceManager { // Perms. void grantSlicePermission(String callingPkg, String toPkg, in Uri uri); void revokeSlicePermission(String callingPkg, String toPkg, in Uri uri); - int checkSlicePermission(in Uri uri, String callingPkg, String pkg, int pid, int uid, + int checkSlicePermission(in Uri uri, String callingPkg, int pid, int uid, in String[] autoGrantPermissions); void grantPermissionFromUser(in Uri uri, String pkg, String callingPkg, boolean allSlices); } diff --git a/core/java/android/app/slice/SliceManager.java b/core/java/android/app/slice/SliceManager.java index 5497b78c3f81..ed4ea749c181 100644 --- a/core/java/android/app/slice/SliceManager.java +++ b/core/java/android/app/slice/SliceManager.java @@ -439,8 +439,8 @@ public class SliceManager { */ public @PermissionResult int checkSlicePermission(@NonNull Uri uri, int pid, int uid) { try { - return mService.checkSlicePermission(uri, mContext.getPackageName(), null, pid, uid, - null); + return mService.checkSlicePermission(uri, mContext.getPackageName(), pid, uid, + null /* autoGrantPermissions */); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -488,17 +488,13 @@ public class SliceManager { * Does the permission check to see if a caller has access to a specific slice. * @hide */ - public void enforceSlicePermission(Uri uri, String pkg, int pid, int uid, - String[] autoGrantPermissions) { + public void enforceSlicePermission(Uri uri, int pid, int uid, String[] autoGrantPermissions) { try { if (UserHandle.isSameApp(uid, Process.myUid())) { return; } - if (pkg == null) { - throw new SecurityException("No pkg specified"); - } - int result = mService.checkSlicePermission(uri, mContext.getPackageName(), pkg, pid, - uid, autoGrantPermissions); + int result = mService.checkSlicePermission(uri, mContext.getPackageName(), pid, uid, + autoGrantPermissions); if (result == PERMISSION_DENIED) { throw new SecurityException("User " + uid + " does not have slice permission for " + uri + "."); diff --git a/core/java/android/app/slice/SliceProvider.java b/core/java/android/app/slice/SliceProvider.java index fb8a83bfc0ef..e6c88a31a1b2 100644 --- a/core/java/android/app/slice/SliceProvider.java +++ b/core/java/android/app/slice/SliceProvider.java @@ -452,8 +452,8 @@ public abstract class SliceProvider extends ContentProvider { String pkg = callingPkg != null ? callingPkg : getContext().getPackageManager().getNameForUid(callingUid); try { - mSliceManager.enforceSlicePermission(sliceUri, pkg, - callingPid, callingUid, mAutoGrantPermissions); + mSliceManager.enforceSlicePermission(sliceUri, callingPid, callingUid, + mAutoGrantPermissions); } catch (SecurityException e) { return createPermissionSlice(getContext(), sliceUri, pkg); } diff --git a/core/java/android/companion/AssociationRequest.java b/core/java/android/companion/AssociationRequest.java index 257530b26eec..75ab11531595 100644 --- a/core/java/android/companion/AssociationRequest.java +++ b/core/java/android/companion/AssociationRequest.java @@ -151,7 +151,7 @@ public final class AssociationRequest implements Parcelable { * The Display name of the device to be shown in the CDM confirmation UI. Must be non-null for * "self-managed" association. */ - private final @Nullable CharSequence mDisplayName; + private @Nullable CharSequence mDisplayName; /** * Whether the association is to be managed by the companion application. @@ -302,6 +302,11 @@ public final class AssociationRequest implements Parcelable { } /** @hide */ + public void setDisplayName(CharSequence displayName) { + mDisplayName = displayName; + } + + /** @hide */ @NonNull @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public List<DeviceFilter<?>> getDeviceFilters() { @@ -597,7 +602,9 @@ public final class AssociationRequest implements Parcelable { boolean forceConfirmation = (flg & 0x20) != 0; boolean skipPrompt = (flg & 0x400) != 0; List<DeviceFilter<?>> deviceFilters = new ArrayList<>(); - in.readParcelableList(deviceFilters, DeviceFilter.class.getClassLoader(), (Class<android.companion.DeviceFilter<?>>) (Class<?>) android.companion.DeviceFilter.class); + in.readParcelableList(deviceFilters, DeviceFilter.class.getClassLoader(), + (Class<android.companion.DeviceFilter<?>>) (Class<?>) + android.companion.DeviceFilter.class); String deviceProfile = (flg & 0x4) == 0 ? null : in.readString(); CharSequence displayName = (flg & 0x8) == 0 ? null : (CharSequence) in.readCharSequence(); String packageName = (flg & 0x40) == 0 ? null : in.readString(); @@ -641,10 +648,10 @@ public final class AssociationRequest implements Parcelable { }; @DataClass.Generated( - time = 1643238443303L, + time = 1649179640045L, codegenVersion = "1.0.23", sourceFile = "frameworks/base/core/java/android/companion/AssociationRequest.java", - inputSignatures = "public static final java.lang.String DEVICE_PROFILE_WATCH\npublic static final @android.annotation.RequiresPermission java.lang.String DEVICE_PROFILE_APP_STREAMING\npublic static final @android.annotation.RequiresPermission java.lang.String DEVICE_PROFILE_AUTOMOTIVE_PROJECTION\npublic static final @android.annotation.RequiresPermission java.lang.String DEVICE_PROFILE_COMPUTER\nprivate final boolean mSingleDevice\nprivate final @com.android.internal.util.DataClass.PluralOf(\"deviceFilter\") @android.annotation.NonNull java.util.List<android.companion.DeviceFilter<?>> mDeviceFilters\nprivate final @android.annotation.Nullable @android.companion.AssociationRequest.DeviceProfile java.lang.String mDeviceProfile\nprivate final @android.annotation.Nullable java.lang.CharSequence mDisplayName\nprivate final boolean mSelfManaged\nprivate final boolean mForceConfirmation\nprivate @android.annotation.Nullable java.lang.String mPackageName\nprivate @android.annotation.UserIdInt int mUserId\nprivate @android.annotation.Nullable java.lang.String mDeviceProfilePrivilegesDescription\nprivate final long mCreationTime\nprivate boolean mSkipPrompt\npublic @android.annotation.Nullable @android.companion.AssociationRequest.DeviceProfile java.lang.String getDeviceProfile()\npublic @android.annotation.Nullable java.lang.CharSequence getDisplayName()\npublic boolean isSelfManaged()\npublic boolean isForceConfirmation()\npublic boolean isSingleDevice()\npublic void setPackageName(java.lang.String)\npublic void setUserId(int)\npublic void setDeviceProfilePrivilegesDescription(java.lang.String)\npublic void setSkipPrompt(boolean)\npublic @android.annotation.NonNull @android.compat.annotation.UnsupportedAppUsage java.util.List<android.companion.DeviceFilter<?>> getDeviceFilters()\nclass AssociationRequest extends java.lang.Object implements [android.os.Parcelable]\nprivate boolean mSingleDevice\nprivate @android.annotation.Nullable java.util.ArrayList<android.companion.DeviceFilter<?>> mDeviceFilters\nprivate @android.annotation.Nullable java.lang.String mDeviceProfile\nprivate @android.annotation.Nullable java.lang.CharSequence mDisplayName\nprivate boolean mSelfManaged\nprivate boolean mForceConfirmation\npublic @android.annotation.NonNull android.companion.AssociationRequest.Builder setSingleDevice(boolean)\npublic @android.annotation.NonNull android.companion.AssociationRequest.Builder addDeviceFilter(android.companion.DeviceFilter<?>)\npublic @android.annotation.NonNull android.companion.AssociationRequest.Builder setDeviceProfile(java.lang.String)\npublic @android.annotation.NonNull android.companion.AssociationRequest.Builder setDisplayName(java.lang.CharSequence)\npublic @android.annotation.RequiresPermission @android.annotation.NonNull android.companion.AssociationRequest.Builder setSelfManaged(boolean)\npublic @android.annotation.RequiresPermission @android.annotation.NonNull android.companion.AssociationRequest.Builder setForceConfirmation(boolean)\npublic @android.annotation.NonNull @java.lang.Override android.companion.AssociationRequest build()\nclass Builder extends android.provider.OneTimeUseBuilder<android.companion.AssociationRequest> implements []\n@com.android.internal.util.DataClass(genConstructor=false, genToString=true, genEqualsHashCode=true, genHiddenGetters=true, genParcelable=true, genConstDefs=false)") + inputSignatures = "public static final java.lang.String DEVICE_PROFILE_WATCH\npublic static final @android.annotation.RequiresPermission java.lang.String DEVICE_PROFILE_APP_STREAMING\npublic static final @android.annotation.RequiresPermission java.lang.String DEVICE_PROFILE_AUTOMOTIVE_PROJECTION\npublic static final @android.annotation.RequiresPermission java.lang.String DEVICE_PROFILE_COMPUTER\nprivate final boolean mSingleDevice\nprivate final @com.android.internal.util.DataClass.PluralOf(\"deviceFilter\") @android.annotation.NonNull java.util.List<android.companion.DeviceFilter<?>> mDeviceFilters\nprivate final @android.annotation.Nullable @android.companion.AssociationRequest.DeviceProfile java.lang.String mDeviceProfile\nprivate @android.annotation.Nullable java.lang.CharSequence mDisplayName\nprivate final boolean mSelfManaged\nprivate final boolean mForceConfirmation\nprivate @android.annotation.Nullable java.lang.String mPackageName\nprivate @android.annotation.UserIdInt int mUserId\nprivate @android.annotation.Nullable java.lang.String mDeviceProfilePrivilegesDescription\nprivate final long mCreationTime\nprivate boolean mSkipPrompt\npublic @android.annotation.Nullable @android.companion.AssociationRequest.DeviceProfile java.lang.String getDeviceProfile()\npublic @android.annotation.Nullable java.lang.CharSequence getDisplayName()\npublic boolean isSelfManaged()\npublic boolean isForceConfirmation()\npublic boolean isSingleDevice()\npublic void setPackageName(java.lang.String)\npublic void setUserId(int)\npublic void setDeviceProfilePrivilegesDescription(java.lang.String)\npublic void setSkipPrompt(boolean)\npublic void setDisplayName(java.lang.CharSequence)\npublic @android.annotation.NonNull @android.compat.annotation.UnsupportedAppUsage java.util.List<android.companion.DeviceFilter<?>> getDeviceFilters()\nclass AssociationRequest extends java.lang.Object implements [android.os.Parcelable]\nprivate boolean mSingleDevice\nprivate @android.annotation.Nullable java.util.ArrayList<android.companion.DeviceFilter<?>> mDeviceFilters\nprivate @android.annotation.Nullable java.lang.String mDeviceProfile\nprivate @android.annotation.Nullable java.lang.CharSequence mDisplayName\nprivate boolean mSelfManaged\nprivate boolean mForceConfirmation\npublic @android.annotation.NonNull android.companion.AssociationRequest.Builder setSingleDevice(boolean)\npublic @android.annotation.NonNull android.companion.AssociationRequest.Builder addDeviceFilter(android.companion.DeviceFilter<?>)\npublic @android.annotation.NonNull android.companion.AssociationRequest.Builder setDeviceProfile(java.lang.String)\npublic @android.annotation.NonNull android.companion.AssociationRequest.Builder setDisplayName(java.lang.CharSequence)\npublic @android.annotation.RequiresPermission @android.annotation.NonNull android.companion.AssociationRequest.Builder setSelfManaged(boolean)\npublic @android.annotation.RequiresPermission @android.annotation.NonNull android.companion.AssociationRequest.Builder setForceConfirmation(boolean)\npublic @android.annotation.NonNull @java.lang.Override android.companion.AssociationRequest build()\nclass Builder extends android.provider.OneTimeUseBuilder<android.companion.AssociationRequest> implements []\n@com.android.internal.util.DataClass(genConstructor=false, genToString=true, genEqualsHashCode=true, genHiddenGetters=true, genParcelable=true, genConstDefs=false)") @Deprecated private void __metadata() {} diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java index 56939f0ae650..10ab034c85a1 100644 --- a/core/java/android/companion/CompanionDeviceManager.java +++ b/core/java/android/companion/CompanionDeviceManager.java @@ -774,7 +774,8 @@ public final class CompanionDeviceManager { } /** - * Dispatch a message to system for processing. + * Dispatch a message to system for processing. It should only be called by + * {@link CompanionDeviceService#dispatchMessageToSystem(int, int, byte[])} * * <p>Calling app must declare uses-permission * {@link android.Manifest.permission#DELIVER_COMPANION_MESSAGES}</p> @@ -874,6 +875,66 @@ public final class CompanionDeviceManager { } } + /** + * Build a permission sync user consent dialog. + * + * <p>Only the companion app which owns the association can call this method. Otherwise a null + * IntentSender will be returned from this method and an error will be logged. + * The The app should launch the {@link Activity} in the returned {@code intentSender} + * {@link IntentSender} by calling + * {@link Activity#startIntentSenderForResult(IntentSender, int, Intent, int, int, int)}.</p> + * + * <p>The permission transfer doesn't happen immediately after the call or user consented. + * The app needs to trigger the system data transfer manually by calling + * {@link #startSystemDataTransfer(int)}, when it confirms the communication channel between + * the two devices is established.</p> + * + * @param associationId The unique {@link AssociationInfo#getId ID} assigned to the association + * of the companion device recorded by CompanionDeviceManager + * @return An {@link IntentSender} that the app should use to launch the UI for + * the user to confirm the system data transfer request. + */ + @UserHandleAware + @Nullable + public IntentSender buildPermissionTransferUserConsentIntent(int associationId) + throws DeviceNotAssociatedException { + try { + PendingIntent pendingIntent = mService.buildPermissionTransferUserConsentIntent( + mContext.getOpPackageName(), + mContext.getUserId(), + associationId); + if (pendingIntent == null) { + return null; + } + return pendingIntent.getIntentSender(); + } catch (RemoteException e) { + ExceptionUtils.propagateIfInstanceOf(e.getCause(), DeviceNotAssociatedException.class); + throw e.rethrowFromSystemServer(); + } + } + + /** + * Start system data transfer which has been previously approved by the user. + * + * <p>Before calling this method, the app needs to make sure there's a communication channel + * between two devices, and has prompted user consent dialogs built by one of these methods: + * {@link #buildPermissionTransferUserConsentIntent(int)}. + * The transfer may fail if the communication channel is disconnected during the transfer.</p> + * + * @param associationId The unique {@link AssociationInfo#getId ID} assigned to the Association + * of the companion device recorded by CompanionDeviceManager + * @throws DeviceNotAssociatedException Exception if the companion device is not associated + */ + @UserHandleAware + public void startSystemDataTransfer(int associationId) throws DeviceNotAssociatedException { + try { + mService.startSystemDataTransfer(mContext.getUserId(), associationId); + } catch (RemoteException e) { + ExceptionUtils.propagateIfInstanceOf(e.getCause(), DeviceNotAssociatedException.class); + throw e.rethrowFromSystemServer(); + } + } + private boolean checkFeaturePresent() { boolean featurePresent = mService != null; if (!featurePresent && DEBUG) { diff --git a/core/java/android/companion/CompanionDeviceService.java b/core/java/android/companion/CompanionDeviceService.java index 9e1bf4bb9484..bb2189d554f3 100644 --- a/core/java/android/companion/CompanionDeviceService.java +++ b/core/java/android/companion/CompanionDeviceService.java @@ -29,6 +29,7 @@ import android.os.IBinder; import android.util.Log; import java.util.Objects; +import java.util.concurrent.Executor; /** * A service that receives calls from the system when the associated companion device appears @@ -152,11 +153,9 @@ public abstract class CompanionDeviceService extends Service { * @param messageId system assigned id of the message to be sent * @param associationId association id of the associated device * @param message message to be sent - * - * @hide */ - @MainThread - public void onDispatchMessage(int messageId, int associationId, @NonNull byte[] message) { + public void onMessageDispatchedFromSystem(int messageId, int associationId, + @NonNull byte[] message) { // do nothing. Companion apps can override this function for system to send messages. } @@ -167,17 +166,31 @@ public abstract class CompanionDeviceService extends Service { * <p>Calling app must declare uses-permission * {@link android.Manifest.permission#DELIVER_COMPANION_MESSAGES}</p> * + * <p>Note 1: messageId was assigned by the system, and sender should send the messageId along + * with the message to the receiver. messageId will later be used for verification purpose. + * Misusing the messageId will result in no action.</p> + * + * <p>Note 2: associationId should be local to your device which is calling this API. It's not + * the associationId on your remote device. If you don't have one, you can call + * {@link CompanionDeviceManager#associate(AssociationRequest, Executor, + * CompanionDeviceManager.Callback)} to create one. Misusing the associationId will result in + * {@link DeviceNotAssociatedException}.</p> + * * @param messageId id of the message * @param associationId id of the associated device - * @param message messaged received from the associated device - * - * @hide + * @param message message received from the associated device */ @RequiresPermission(android.Manifest.permission.DELIVER_COMPANION_MESSAGES) - public final void dispatchMessage(int messageId, int associationId, @NonNull byte[] message) { + public final void dispatchMessageToSystem(int messageId, int associationId, + @NonNull byte[] message) + throws DeviceNotAssociatedException { CompanionDeviceManager companionDeviceManager = getSystemService(CompanionDeviceManager.class); - companionDeviceManager.dispatchMessage(messageId, associationId, message); + if (companionDeviceManager != null) { + companionDeviceManager.dispatchMessage(messageId, associationId, message); + } else { + Log.e(LOG_TAG, "CompanionDeviceManager is null. Can't dispatch messages."); + } } /** @@ -239,9 +252,11 @@ public abstract class CompanionDeviceService extends Service { } @Override - public void onDispatchMessage(int messageId, int associationId, @NonNull byte[] message) { + public void onMessageDispatchedFromSystem(int messageId, int associationId, + @NonNull byte[] message) { mMainHandler.postAtFrontOfQueue( - () -> mService.onDispatchMessage(messageId, associationId, message)); + () -> mService.onMessageDispatchedFromSystem(messageId, associationId, + message)); } } } diff --git a/core/java/android/companion/ICompanionDeviceManager.aidl b/core/java/android/companion/ICompanionDeviceManager.aidl index 68a6031f543f..f5b69387c467 100644 --- a/core/java/android/companion/ICompanionDeviceManager.aidl +++ b/core/java/android/companion/ICompanionDeviceManager.aidl @@ -62,7 +62,7 @@ interface ICompanionDeviceManager { void createAssociation(in String packageName, in String macAddress, int userId, in byte[] certificate); - void dispatchMessage(in int messageId, in int associationId, in byte[] message); + void dispatchMessage(int messageId, int associationId, in byte[] message); void addOnAssociationsChangedListener(IOnAssociationsChangedListener listener, int userId); @@ -71,4 +71,9 @@ interface ICompanionDeviceManager { void notifyDeviceAppeared(int associationId); void notifyDeviceDisappeared(int associationId); + + PendingIntent buildPermissionTransferUserConsentIntent(String callingPackage, int userId, + int associationId); + + void startSystemDataTransfer(int userId, int associationId); } diff --git a/core/java/android/companion/ICompanionDeviceService.aidl b/core/java/android/companion/ICompanionDeviceService.aidl index 4e453573f62e..3c90b86ca8c0 100644 --- a/core/java/android/companion/ICompanionDeviceService.aidl +++ b/core/java/android/companion/ICompanionDeviceService.aidl @@ -22,5 +22,5 @@ import android.companion.AssociationInfo; oneway interface ICompanionDeviceService { void onDeviceAppeared(in AssociationInfo associationInfo); void onDeviceDisappeared(in AssociationInfo associationInfo); - void onDispatchMessage(in int messageId, in int associationId, in byte[] message); + void onMessageDispatchedFromSystem(in int messageId, in int associationId, in byte[] message); } diff --git a/core/java/android/companion/SystemDataTransferRequest.java b/core/java/android/companion/SystemDataTransferRequest.java deleted file mode 100644 index e3b0369e203d..000000000000 --- a/core/java/android/companion/SystemDataTransferRequest.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.companion; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.os.Parcel; -import android.os.Parcelable; -import android.provider.OneTimeUseBuilder; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * A request for users to allow the companion app to transfer system data to the companion devices. - * - * @hide - */ -public final class SystemDataTransferRequest implements Parcelable { - - private final int mAssociationId; - private final boolean mPermissionSyncAllPackages; - private final List<String> mPermissionSyncPackages; - - /** - * @hide - */ - public SystemDataTransferRequest(int associationId, boolean syncAllPackages, - @Nullable List<String> permissionSyncPackages) { - mAssociationId = associationId; - mPermissionSyncAllPackages = syncAllPackages; - mPermissionSyncPackages = permissionSyncPackages; - } - - public int getAssociationId() { - return mAssociationId; - } - - @NonNull - public boolean isPermissionSyncAllPackages() { - return mPermissionSyncAllPackages; - } - - @NonNull - public List<String> getPermissionSyncPackages() { - return mPermissionSyncPackages; - } - - /** - * A builder for {@link SystemDataTransferRequest}. - * - * <p>You have to call one of the below methods to create a valid request</p> - * <br>1. {@link #setPermissionSyncAllPackages()} - * <br>2. {@link #setPermissionSyncPackages(List)} - */ - public static final class Builder extends OneTimeUseBuilder<SystemDataTransferRequest> { - - private final int mAssociationId; - private boolean mPermissionSyncAllPackages; - private List<String> mPermissionSyncPackages = new ArrayList<>(); - - public Builder(int associationId) { - mAssociationId = associationId; - } - - /** - * Call to sync permissions for all the packages. You can optionally call - * {@link #setPermissionSyncPackages(List)} to specify the packages to sync permissions. - * - * <p>The system will only sync permissions that are explicitly granted by the user.</p> - * - * <p>If a permission is granted or revoked by the system or a policy, even if the user has - * explicitly granted or revoked the permission earlier, the permission will be ignored.</p> - * - * <p>If a system or policy granted or revoked permission is granted or revoked by the user - * later, the permission will be ignored.</p> - * - * @see #setPermissionSyncPackages(List) - * - * @return the builder - */ - @NonNull - public Builder setPermissionSyncAllPackages() { - mPermissionSyncAllPackages = true; - return this; - } - - /** - * Set a list of packages to sync permissions. You can optionally call - * {@link #setPermissionSyncAllPackages()} to sync permissions for all the packages. - * - * @see #setPermissionSyncAllPackages() - * - * @param permissionSyncPackages packages to sync permissions - * @return builder - */ - @NonNull - public Builder setPermissionSyncPackages(@NonNull List<String> permissionSyncPackages) { - mPermissionSyncPackages = permissionSyncPackages; - return this; - } - - @Override - @NonNull - public SystemDataTransferRequest build() { - return new SystemDataTransferRequest(mAssociationId, mPermissionSyncAllPackages, - mPermissionSyncPackages); - } - } - - SystemDataTransferRequest(Parcel in) { - mAssociationId = in.readInt(); - mPermissionSyncAllPackages = in.readBoolean(); - mPermissionSyncPackages = Arrays.asList(in.createString8Array()); - } - - @Override - public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeInt(mAssociationId); - dest.writeBoolean(mPermissionSyncAllPackages); - dest.writeString8Array(mPermissionSyncPackages.toArray(new String[0])); - } - - @Override - public int describeContents() { - return 0; - } - - @NonNull - public static final Creator<SystemDataTransferRequest> CREATOR = - new Creator<SystemDataTransferRequest>() { - @Override - public SystemDataTransferRequest createFromParcel(Parcel in) { - return new SystemDataTransferRequest(in); - } - - @Override - public SystemDataTransferRequest[] newArray(int size) { - return new SystemDataTransferRequest[size]; - } - }; -} diff --git a/core/java/android/companion/SystemDataTransferRequest.aidl b/core/java/android/companion/datatransfer/PermissionSyncRequest.aidl index 19ae60effa7a..76a92e33e544 100644 --- a/core/java/android/companion/SystemDataTransferRequest.aidl +++ b/core/java/android/companion/datatransfer/PermissionSyncRequest.aidl @@ -14,6 +14,6 @@ * limitations under the License. */ -package android.companion; +package android.companion.datatransfer; -parcelable SystemDataTransferRequest; +parcelable PermissionSyncRequest; diff --git a/core/java/android/companion/datatransfer/PermissionSyncRequest.java b/core/java/android/companion/datatransfer/PermissionSyncRequest.java new file mode 100644 index 000000000000..973fca30c765 --- /dev/null +++ b/core/java/android/companion/datatransfer/PermissionSyncRequest.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.companion.datatransfer; + +import android.annotation.NonNull; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * The permission sync request class. + * + * @hide + */ +public class PermissionSyncRequest extends SystemDataTransferRequest implements Parcelable { + + /** @hide */ + public PermissionSyncRequest(int associationId) { + super(associationId, DATA_TYPE_PERMISSION_SYNC); + } + + /** @hide */ + @Override + public String toString() { + return "SystemDataTransferRequest(" + + "associationId=" + mAssociationId + + ", userId=" + mUserId + + ", isUserConsented=" + mUserConsented + + ")"; + } + + /** @hide */ + PermissionSyncRequest(Parcel in) { + super(in); + } + + /** @hide */ + @NonNull + public static final Creator<PermissionSyncRequest> CREATOR = + new Creator<PermissionSyncRequest>() { + @Override + public PermissionSyncRequest createFromParcel(Parcel in) { + return new PermissionSyncRequest(in); + } + + @Override + public PermissionSyncRequest[] newArray(int size) { + return new PermissionSyncRequest[size]; + } + }; +} diff --git a/core/java/android/companion/datatransfer/SystemDataTransferRequest.java b/core/java/android/companion/datatransfer/SystemDataTransferRequest.java new file mode 100644 index 000000000000..38a553d8a725 --- /dev/null +++ b/core/java/android/companion/datatransfer/SystemDataTransferRequest.java @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.companion.datatransfer; + +import android.annotation.NonNull; +import android.annotation.UserIdInt; +import android.os.Parcel; + +/** + * A request for users to allow the companion app to transfer system data to the companion devices. + * + * @hide + */ +public abstract class SystemDataTransferRequest { + + /** @hide */ + public static final int DATA_TYPE_PERMISSION_SYNC = 1; + + final int mAssociationId; + + final int mDataType; + + /** + * User id that the request belongs to. + * Populated by the system. + */ + @UserIdInt + int mUserId; + + /** + * Whether the request is consented by the user. + * Populated by the system + */ + boolean mUserConsented = false; + + /** @hide */ + SystemDataTransferRequest(int associationId, int dataType) { + mAssociationId = associationId; + mDataType = dataType; + } + + /** @hide */ + public int getAssociationId() { + return mAssociationId; + } + + /** @hide */ + public int getDataType() { + return mDataType; + } + + /** @hide */ + public int getUserId() { + return mUserId; + } + + /** @hide */ + public boolean isUserConsented() { + return mUserConsented; + } + + /** @hide */ + public void setUserId(@UserIdInt int userId) { + mUserId = userId; + } + + /** @hide */ + public void setUserConsented(boolean isUserConsented) { + mUserConsented = isUserConsented; + } + + /** @hide */ + SystemDataTransferRequest(Parcel in) { + mAssociationId = in.readInt(); + mDataType = in.readInt(); + mUserId = in.readInt(); + mUserConsented = in.readBoolean(); + } + + /** @hide */ + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeInt(mAssociationId); + dest.writeInt(mDataType); + dest.writeInt(mUserId); + dest.writeBoolean(mUserConsented); + } + + /** @hide */ + public int describeContents() { + return 0; + } +} diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java index f4de82946253..970849373fb4 100644 --- a/core/java/android/content/pm/PackageInfo.java +++ b/core/java/android/content/pm/PackageInfo.java @@ -448,6 +448,12 @@ public class PackageInfo implements Parcelable { */ public boolean isApex; + /** + * Whether this is an active APEX package. + * @hide + */ + public boolean isActiveApex; + public PackageInfo() { } @@ -534,6 +540,7 @@ public class PackageInfo implements Parcelable { dest.writeInt(0); } dest.writeBoolean(isApex); + dest.writeBoolean(isActiveApex); dest.restoreAllowSquashing(prevAllowSquashing); } @@ -598,5 +605,6 @@ public class PackageInfo implements Parcelable { signingInfo = SigningInfo.CREATOR.createFromParcel(source); } isApex = source.readBoolean(); + isActiveApex = source.readBoolean(); } } diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index 236c24475844..5f45c342a27c 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -682,7 +682,9 @@ public class PackageInstaller { * </ul> * * @param packageName The package to uninstall. - * @param statusReceiver Where to deliver the result. + * @param statusReceiver Where to deliver the result of the operation indicated by the extra + * {@link #EXTRA_STATUS}. Refer to the individual status codes + * on how to handle them. * * @see android.app.admin.DevicePolicyManager */ @@ -700,7 +702,9 @@ public class PackageInstaller { * * @param packageName The package to uninstall. * @param flags Flags for uninstall. - * @param statusReceiver Where to deliver the result. + * @param statusReceiver Where to deliver the result of the operation indicated by the extra + * {@link #EXTRA_STATUS}. Refer to the individual status codes + * on how to handle them. * * @hide */ @@ -725,7 +729,9 @@ public class PackageInstaller { * </ul> * * @param versionedPackage The versioned package to uninstall. - * @param statusReceiver Where to deliver the result. + * @param statusReceiver Where to deliver the result of the operation indicated by the extra + * {@link #EXTRA_STATUS}. Refer to the individual status codes + * on how to handle them. * * @see android.app.admin.DevicePolicyManager */ @@ -747,7 +753,9 @@ public class PackageInstaller { * * @param versionedPackage The versioned package to uninstall. * @param flags Flags for uninstall. - * @param statusReceiver Where to deliver the result. + * @param statusReceiver Where to deliver the result of the operation indicated by the extra + * {@link #EXTRA_STATUS}. Refer to the individual status codes + * on how to handle them. * * @hide */ @@ -775,7 +783,9 @@ public class PackageInstaller { * * @param packageName The package to install. * @param installReason Reason for install. - * @param statusReceiver Where to deliver the result. + * @param statusReceiver Where to deliver the result of the operation indicated by the extra + * {@link #EXTRA_STATUS}. Refer to the individual status codes + * on how to handle them. */ @RequiresPermission(allOf = { Manifest.permission.INSTALL_PACKAGES, @@ -797,8 +807,10 @@ public class PackageInstaller { * Uninstall the given package for the user for which this installer was created if the package * will still exist for other users on the device. * - * @param packageName The package to install. - * @param statusReceiver Where to deliver the result. + * @param packageName The package to uninstall. + * @param statusReceiver Where to deliver the result of the operation indicated by the extra + * {@link #EXTRA_STATUS}. Refer to the individual status codes + * on how to handle them. */ @RequiresPermission(Manifest.permission.DELETE_PACKAGES) public void uninstallExistingPackage(@NonNull String packageName, @@ -1705,20 +1717,22 @@ public class PackageInstaller { public @interface UserActionRequirement {} /** - * The installer did not call {@link SessionParams#setRequireUserAction(int)} to - * specify whether user action should be required for the install. + * This value is passed by the installer to {@link SessionParams#setRequireUserAction(int)} + * to indicate that user action is unspecified for this install. + * {@code requireUserAction} also defaults to this value unless modified by + * {@link SessionParams#setRequireUserAction(int)} */ public static final int USER_ACTION_UNSPECIFIED = 0; /** - * The installer called {@link SessionParams#setRequireUserAction(int)} with - * {@code true} to require user action for the install to complete. + * This value is passed by the installer to {@link SessionParams#setRequireUserAction(int)} + * to indicate that user action is required for this install. */ public static final int USER_ACTION_REQUIRED = 1; /** - * The installer called {@link SessionParams#setRequireUserAction(int)} with - * {@code false} to request that user action not be required for this install. + * This value is passed by the installer to {@link SessionParams#setRequireUserAction(int)} + * to indicate that user action is not required for this install. */ public static final int USER_ACTION_NOT_REQUIRED = 2; diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index a90f6d625c51..6f9ec9c780fb 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -4247,6 +4247,7 @@ public abstract class PackageManager { */ public static final String EXTRA_VERIFICATION_PACKAGE_NAME = "android.content.pm.extra.VERIFICATION_PACKAGE_NAME"; + /** * Extra field name for the result of a verification, either * {@link #VERIFICATION_ALLOW}, or {@link #VERIFICATION_REJECT}. @@ -4256,6 +4257,14 @@ public abstract class PackageManager { = "android.content.pm.extra.VERIFICATION_RESULT"; /** + * Extra field name for tracking whether user action + * was requested for a particular install, either {@code true} or {@code false}. + * @hide + */ + public static final String EXTRA_USER_ACTION_REQUIRED + = "android.content.pm.extra.USER_ACTION_REQUIRED"; + + /** * Extra field name for the version code of a package pending verification. * @deprecated Use {@link #EXTRA_VERIFICATION_LONG_VERSION_CODE} instead. * @hide @@ -4265,8 +4274,7 @@ public abstract class PackageManager { = "android.content.pm.extra.VERIFICATION_VERSION_CODE"; /** - * Extra field name for the long version code of a package pending verification. - * + * Extra field name for the long version code of a package pending verification * @hide */ public static final String EXTRA_VERIFICATION_LONG_VERSION_CODE = diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java index 76e9fcb07f22..816460b01529 100644 --- a/core/java/android/content/pm/UserInfo.java +++ b/core/java/android/content/pm/UserInfo.java @@ -142,6 +142,22 @@ public class UserInfo implements Parcelable { public static final int FLAG_PROFILE = 0x00001000; /** + * Indicates that this user is created in ephemeral mode via + * {@link IUserManager} create user. + * + * When a user is created with {@link #FLAG_EPHEMERAL}, {@link #FLAG_EPHEMERAL_ON_CREATE} + * is set internally within the user manager. + * + * When {@link #FLAG_EPHEMERAL_ON_CREATE} is set {@link IUserManager.setUserEphemeral} + * has no effect because a user that was created ephemeral can never be made non-ephemeral. + * + * {@link #FLAG_EPHEMERAL_ON_CREATE} should NOT be set by client's of user manager + * + * @hide + */ + public static final int FLAG_EPHEMERAL_ON_CREATE = 0x00002000; + + /** * @hide */ @IntDef(flag = true, prefix = "FLAG_", value = { @@ -157,7 +173,8 @@ public class UserInfo implements Parcelable { FLAG_DEMO, FLAG_FULL, FLAG_SYSTEM, - FLAG_PROFILE + FLAG_PROFILE, + FLAG_EPHEMERAL_ON_CREATE }) @Retention(RetentionPolicy.SOURCE) public @interface UserInfoFlag { diff --git a/core/java/android/content/pm/verify/domain/TEST_MAPPING b/core/java/android/content/pm/verify/domain/TEST_MAPPING index ba4a62cdbbf1..8a1982a339ea 100644 --- a/core/java/android/content/pm/verify/domain/TEST_MAPPING +++ b/core/java/android/content/pm/verify/domain/TEST_MAPPING @@ -12,9 +12,6 @@ "name": "CtsDomainVerificationDeviceStandaloneTestCases" }, { - "name": "CtsDomainVerificationDeviceMultiUserTestCases" - }, - { "name": "CtsDomainVerificationHostTestCases" } ] diff --git a/core/java/android/hardware/IConsumerIrService.aidl b/core/java/android/hardware/IConsumerIrService.aidl index c79bd1958226..930c73f0ae44 100644 --- a/core/java/android/hardware/IConsumerIrService.aidl +++ b/core/java/android/hardware/IConsumerIrService.aidl @@ -19,8 +19,13 @@ package android.hardware; /** {@hide} */ interface IConsumerIrService { + @RequiresNoPermission boolean hasIrEmitter(); + + @EnforcePermission("TRANSMIT_IR") void transmit(String packageName, int carrierFrequency, in int[] pattern); + + @EnforcePermission("TRANSMIT_IR") int[] getCarrierFrequencies(); } diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java index dc65beffa6e5..d235f124de32 100644 --- a/core/java/android/hardware/biometrics/BiometricPrompt.java +++ b/core/java/android/hardware/biometrics/BiometricPrompt.java @@ -422,6 +422,18 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan } /** + * Set if BiometricPrompt is being used by the legacy fingerprint manager API. + * @param sensorId sensor id + * @return This builder. + * @hide + */ + @NonNull + public Builder setIsForLegacyFingerprintManager(int sensorId) { + mPromptInfo.setIsForLegacyFingerprintManager(sensorId); + return this; + } + + /** * Creates a {@link BiometricPrompt}. * * @return An instance of {@link BiometricPrompt}. @@ -883,28 +895,36 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan @NonNull @CallbackExecutor Executor executor, @NonNull AuthenticationCallback callback, int userId) { - authenticateUserForOperation(cancel, executor, callback, userId, 0 /* operationId */); + if (cancel == null) { + throw new IllegalArgumentException("Must supply a cancellation signal"); + } + if (executor == null) { + throw new IllegalArgumentException("Must supply an executor"); + } + if (callback == null) { + throw new IllegalArgumentException("Must supply a callback"); + } + + authenticateInternal(0 /* operationId */, cancel, executor, callback, userId); } /** - * Authenticates for the given user and keystore operation. + * Authenticates for the given keystore operation. * * @param cancel An object that can be used to cancel authentication * @param executor An executor to handle callback events * @param callback An object to receive authentication events - * @param userId The user to authenticate * @param operationId The keystore operation associated with authentication * * @return A requestId that can be used to cancel this operation. * * @hide */ - @RequiresPermission(USE_BIOMETRIC_INTERNAL) - public long authenticateUserForOperation( + @RequiresPermission(USE_BIOMETRIC) + public long authenticateForOperation( @NonNull CancellationSignal cancel, @NonNull @CallbackExecutor Executor executor, @NonNull AuthenticationCallback callback, - int userId, long operationId) { if (cancel == null) { throw new IllegalArgumentException("Must supply a cancellation signal"); @@ -916,7 +936,7 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan throw new IllegalArgumentException("Must supply a callback"); } - return authenticateInternal(operationId, cancel, executor, callback, userId); + return authenticateInternal(operationId, cancel, executor, callback, mContext.getUserId()); } /** @@ -1050,7 +1070,7 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan private void cancelAuthentication(long requestId) { if (mService != null) { try { - mService.cancelAuthentication(mToken, mContext.getOpPackageName(), requestId); + mService.cancelAuthentication(mToken, mContext.getPackageName(), requestId); } catch (RemoteException e) { Log.e(TAG, "Unable to cancel authentication", e); } @@ -1109,7 +1129,7 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan } final long authId = mService.authenticate(mToken, operationId, userId, - mBiometricServiceReceiver, mContext.getOpPackageName(), promptInfo); + mBiometricServiceReceiver, mContext.getPackageName(), promptInfo); cancel.setOnCancelListener(new OnAuthenticationCancelListener(authId)); return authId; } catch (RemoteException e) { diff --git a/core/java/android/hardware/biometrics/ITestSessionCallback.aidl b/core/java/android/hardware/biometrics/ITestSessionCallback.aidl index 3d9517f29548..b336a9f21b60 100644 --- a/core/java/android/hardware/biometrics/ITestSessionCallback.aidl +++ b/core/java/android/hardware/biometrics/ITestSessionCallback.aidl @@ -19,7 +19,7 @@ package android.hardware.biometrics; * ITestSession callback for FingerprintManager and BiometricManager. * @hide */ -interface ITestSessionCallback { +oneway interface ITestSessionCallback { void onCleanupStarted(int userId); void onCleanupFinished(int userId); } diff --git a/core/java/android/hardware/biometrics/PromptInfo.java b/core/java/android/hardware/biometrics/PromptInfo.java index 0c03948e5368..a6b8096e6d4f 100644 --- a/core/java/android/hardware/biometrics/PromptInfo.java +++ b/core/java/android/hardware/biometrics/PromptInfo.java @@ -46,6 +46,7 @@ public class PromptInfo implements Parcelable { @NonNull private List<Integer> mAllowedSensorIds = new ArrayList<>(); private boolean mAllowBackgroundAuthentication; private boolean mIgnoreEnrollmentState; + private boolean mIsForLegacyFingerprintManager = false; public PromptInfo() { @@ -68,6 +69,7 @@ public class PromptInfo implements Parcelable { mAllowedSensorIds = in.readArrayList(Integer.class.getClassLoader(), java.lang.Integer.class); mAllowBackgroundAuthentication = in.readBoolean(); mIgnoreEnrollmentState = in.readBoolean(); + mIsForLegacyFingerprintManager = in.readBoolean(); } public static final Creator<PromptInfo> CREATOR = new Creator<PromptInfo>() { @@ -105,10 +107,15 @@ public class PromptInfo implements Parcelable { dest.writeList(mAllowedSensorIds); dest.writeBoolean(mAllowBackgroundAuthentication); dest.writeBoolean(mIgnoreEnrollmentState); + dest.writeBoolean(mIsForLegacyFingerprintManager); } public boolean containsTestConfigurations() { - if (!mAllowedSensorIds.isEmpty()) { + if (mIsForLegacyFingerprintManager + && mAllowedSensorIds.size() == 1 + && !mAllowBackgroundAuthentication) { + return false; + } else if (!mAllowedSensorIds.isEmpty()) { return true; } else if (mAllowBackgroundAuthentication) { return true; @@ -188,7 +195,8 @@ public class PromptInfo implements Parcelable { } public void setAllowedSensorIds(@NonNull List<Integer> sensorIds) { - mAllowedSensorIds = sensorIds; + mAllowedSensorIds.clear(); + mAllowedSensorIds.addAll(sensorIds); } public void setAllowBackgroundAuthentication(boolean allow) { @@ -199,6 +207,12 @@ public class PromptInfo implements Parcelable { mIgnoreEnrollmentState = ignoreEnrollmentState; } + public void setIsForLegacyFingerprintManager(int sensorId) { + mIsForLegacyFingerprintManager = true; + mAllowedSensorIds.clear(); + mAllowedSensorIds.add(sensorId); + } + // Getters public CharSequence getTitle() { @@ -272,4 +286,8 @@ public class PromptInfo implements Parcelable { public boolean isIgnoreEnrollmentState() { return mIgnoreEnrollmentState; } + + public boolean isForLegacyFingerprintManager() { + return mIsForLegacyFingerprintManager; + } } diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java index a62bbf623000..36b532f1cbed 100644 --- a/core/java/android/hardware/display/DisplayManagerGlobal.java +++ b/core/java/android/hardware/display/DisplayManagerGlobal.java @@ -41,6 +41,7 @@ import android.os.Looper; import android.os.Message; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.Trace; import android.util.Log; import android.util.Pair; import android.util.SparseArray; @@ -987,7 +988,8 @@ public final class DisplayManagerGlobal { @Override public void onDisplayEvent(int displayId, @DisplayEvent int event) { if (DEBUG) { - Log.d(TAG, "onDisplayEvent: displayId=" + displayId + ", event=" + event); + Log.d(TAG, "onDisplayEvent: displayId=" + displayId + ", event=" + eventToString( + event)); } handleDisplayEvent(displayId, event); } @@ -1021,6 +1023,12 @@ public final class DisplayManagerGlobal { @Override public void handleMessage(Message msg) { + if (DEBUG) { + Trace.beginSection( + "DisplayListenerDelegate(" + eventToString(msg.what) + + ", display=" + msg.arg1 + + ", listener=" + mListener.getClass() + ")"); + } switch (msg.what) { case EVENT_DISPLAY_ADDED: if ((mEventsMask & DisplayManager.EVENT_FLAG_DISPLAY_ADDED) != 0) { @@ -1047,6 +1055,9 @@ public final class DisplayManagerGlobal { } break; } + if (DEBUG) { + Trace.endSection(); + } } } @@ -1150,4 +1161,18 @@ public final class DisplayManagerGlobal { updateCallbackIfNeededLocked(); } } + + private static String eventToString(@DisplayEvent int event) { + switch (event) { + case EVENT_DISPLAY_ADDED: + return "ADDED"; + case EVENT_DISPLAY_CHANGED: + return "CHANGED"; + case EVENT_DISPLAY_REMOVED: + return "REMOVED"; + case EVENT_DISPLAY_BRIGHTNESS_CHANGED: + return "BRIGHTNESS_CHANGED"; + } + return "UNKNOWN"; + } } diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl index e1ffd4a6761d..bb8af8fed962 100644 --- a/core/java/android/hardware/input/IInputManager.aidl +++ b/core/java/android/hardware/input/IInputManager.aidl @@ -38,6 +38,8 @@ import android.view.VerifiedInputEvent; /** @hide */ interface IInputManager { + // Gets the current VelocityTracker strategy + String getVelocityTrackerStrategy(); // Gets input device information. InputDevice getInputDevice(int deviceId); int[] getInputDeviceIds(); diff --git a/core/java/android/hardware/input/InputDeviceIdentifier.java b/core/java/android/hardware/input/InputDeviceIdentifier.java index a5b9a2a4da76..3fd0e3154199 100644 --- a/core/java/android/hardware/input/InputDeviceIdentifier.java +++ b/core/java/android/hardware/input/InputDeviceIdentifier.java @@ -88,6 +88,12 @@ public final class InputDeviceIdentifier implements Parcelable { return Objects.hash(mDescriptor, mVendorId, mProductId); } + @Override + public String toString() { + return "InputDeviceIdentifier: vendorId: " + mVendorId + ", productId: " + mProductId + + ", descriptor: " + mDescriptor; + } + public static final @android.annotation.NonNull Parcelable.Creator<InputDeviceIdentifier> CREATOR = new Parcelable.Creator<InputDeviceIdentifier>() { diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java index cc5b275bbf5a..90db4614bf63 100644 --- a/core/java/android/hardware/input/InputManager.java +++ b/core/java/android/hardware/input/InputManager.java @@ -80,7 +80,8 @@ import java.util.List; @SystemService(Context.INPUT_SERVICE) public final class InputManager { private static final String TAG = "InputManager"; - private static final boolean DEBUG = false; + // To enable these logs, run: 'adb shell setprop log.tag.InputManager DEBUG' (requires restart) + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private static final int MSG_DEVICE_ADDED = 1; private static final int MSG_DEVICE_REMOVED = 2; @@ -272,8 +273,15 @@ public final class InputManager { */ public static final int SWITCH_STATE_ON = 1; + private static String sVelocityTrackerStrategy; + private InputManager(IInputManager im) { mIm = im; + try { + sVelocityTrackerStrategy = mIm.getVelocityTrackerStrategy(); + } catch (RemoteException ex) { + Log.w(TAG, "Could not get VelocityTracker strategy: " + ex); + } } /** @@ -326,10 +334,19 @@ public final class InputManager { } /** + * Get the current VelocityTracker strategy. Only works when the system has fully booted up. + * @hide + */ + public String getVelocityTrackerStrategy() { + return sVelocityTrackerStrategy; + } + + /** * Gets information about the input device with the specified id. * @param id The device id. * @return The input device or null if not found. */ + @Nullable public InputDevice getInputDevice(int id) { synchronized (mInputDevicesLock) { populateInputDevicesLocked(); @@ -1377,6 +1394,7 @@ public final class InputManager { * </p> * @hide */ + @TestApi public void addUniqueIdAssociation(@NonNull String inputPort, @NonNull String displayUniqueId) { try { mIm.addUniqueIdAssociation(inputPort, displayUniqueId); @@ -1393,6 +1411,7 @@ public final class InputManager { * </p> * @hide */ + @TestApi public void removeUniqueIdAssociation(@NonNull String inputPort) { try { mIm.removeUniqueIdAssociation(inputPort); diff --git a/core/java/android/hardware/input/KeyboardLayout.java b/core/java/android/hardware/input/KeyboardLayout.java index 5bdbae39b5dd..52c15519907a 100644 --- a/core/java/android/hardware/input/KeyboardLayout.java +++ b/core/java/android/hardware/input/KeyboardLayout.java @@ -21,8 +21,6 @@ import android.os.LocaleList; import android.os.Parcel; import android.os.Parcelable; -import java.util.Locale; - /** * Describes a keyboard layout. * @@ -157,9 +155,12 @@ public final class KeyboardLayout implements Parcelable, @Override public String toString() { - if (mCollection.isEmpty()) { - return mLabel; - } - return mLabel + " - " + mCollection; + String collectionString = mCollection.isEmpty() ? "" : " - " + mCollection; + return "KeyboardLayout " + mLabel + collectionString + + ", descriptor: " + mDescriptor + + ", priority: " + mPriority + + ", locales: " + mLocales.toString() + + ", vendorId: " + mVendorId + + ", productId: " + mProductId; } } diff --git a/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java b/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java index 3a6d5087c260..694d6d8c23c0 100644 --- a/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java +++ b/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java @@ -40,11 +40,11 @@ import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; @@ -151,7 +151,7 @@ public class KeyphraseEnrollmentInfo { return; } - List<String> parseErrors = new LinkedList<>(); + List<String> parseErrors = new ArrayList<>(); mKeyphrasePackageMap = new HashMap<>(); for (ResolveInfo ri : ris) { try { diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 4fdd53425328..378b366d893e 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -143,6 +143,7 @@ import com.android.internal.inputmethod.ImeTracing; import com.android.internal.inputmethod.InputMethodNavButtonFlags; import com.android.internal.inputmethod.InputMethodPrivilegedOperations; import com.android.internal.inputmethod.InputMethodPrivilegedOperationsRegistry; +import com.android.internal.inputmethod.SoftInputShowHideReason; import com.android.internal.util.RingBuffer; import com.android.internal.view.IInlineSuggestionsRequestCallback; import com.android.internal.view.IInputContext; @@ -1059,7 +1060,7 @@ public class InputMethodService extends AbstractInputMethodService { } private void notifyImeHidden() { - requestHideSelf(0); + requestHideSelf(0 /* flags */, SoftInputShowHideReason.HIDE_SOFT_INPUT_BY_INSETS_API); } private void scheduleImeSurfaceRemoval() { @@ -2907,9 +2908,13 @@ public class InputMethodService extends AbstractInputMethodService { * @param flags Provides additional operating flags. */ public void requestHideSelf(int flags) { + requestHideSelf(flags, SoftInputShowHideReason.HIDE_SOFT_INPUT_FROM_IME); + } + + private void requestHideSelf(int flags, @SoftInputShowHideReason int reason) { ImeTracing.getInstance().triggerServiceDump("InputMethodService#requestHideSelf", mDumper, null /* icProto */); - mPrivOps.hideMySoftInput(flags); + mPrivOps.hideMySoftInput(flags, reason); } /** @@ -2930,7 +2935,9 @@ public class InputMethodService extends AbstractInputMethodService { if (mShowInputRequested) { // If the soft input area is shown, back closes it and we // consume the back key. - if (doIt) requestHideSelf(0); + if (doIt) { + requestHideSelf(0 /* flags */, SoftInputShowHideReason.HIDE_SOFT_INPUT_BY_BACK_KEY); + } return true; } else if (mDecorViewVisible) { if (mCandidatesVisibility == View.VISIBLE) { @@ -3081,7 +3088,8 @@ public class InputMethodService extends AbstractInputMethodService { private void onToggleSoftInput(int showFlags, int hideFlags) { if (DEBUG) Log.v(TAG, "toggleSoftInput()"); if (isInputViewShown()) { - requestHideSelf(hideFlags); + requestHideSelf( + hideFlags, SoftInputShowHideReason.HIDE_SOFT_INPUT_IME_TOGGLE_SOFT_INPUT); } else { requestShowSelf(showFlags); } @@ -3516,7 +3524,8 @@ public class InputMethodService extends AbstractInputMethodService { */ public void onExtractingInputChanged(EditorInfo ei) { if (ei.inputType == InputType.TYPE_NULL) { - requestHideSelf(InputMethodManager.HIDE_NOT_ALWAYS); + requestHideSelf(InputMethodManager.HIDE_NOT_ALWAYS, + SoftInputShowHideReason.HIDE_SOFT_INPUT_EXTRACT_INPUT_CHANGED); } } diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java index 815e4f0c9071..d71faee4cc8d 100644 --- a/core/java/android/net/Uri.java +++ b/core/java/android/net/Uri.java @@ -1205,13 +1205,16 @@ public abstract class Uri implements Parcelable, Comparable<Uri> { } static Uri readFrom(Parcel parcel) { - return new HierarchicalUri( - parcel.readString8(), - Part.readFrom(parcel), - PathPart.readFrom(parcel), - Part.readFrom(parcel), - Part.readFrom(parcel) - ); + final String scheme = parcel.readString8(); + final Part authority = Part.readFrom(parcel); + // In RFC3986 the path should be determined based on whether there is a scheme or + // authority present (https://www.rfc-editor.org/rfc/rfc3986.html#section-3.3). + final boolean hasSchemeOrAuthority = + (scheme != null && scheme.length() > 0) || !authority.isEmpty(); + final PathPart path = PathPart.readFrom(hasSchemeOrAuthority, parcel); + final Part query = Part.readFrom(parcel); + final Part fragment = Part.readFrom(parcel); + return new HierarchicalUri(scheme, authority, path, query, fragment); } public int describeContents() { @@ -2270,6 +2273,11 @@ public abstract class Uri implements Parcelable, Comparable<Uri> { } } + static PathPart readFrom(boolean hasSchemeOrAuthority, Parcel parcel) { + final PathPart path = readFrom(parcel); + return hasSchemeOrAuthority ? makeAbsolute(path) : path; + } + /** * Creates a path from the encoded string. * diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 0b956f8bf9e0..dbd602f27c11 100755 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -1167,6 +1167,11 @@ public class Build { * Tiramisu. */ public static final int TIRAMISU = 33; + + /** + * Upside Down Cake. + */ + public static final int UPSIDE_DOWN_CAKE = CUR_DEVELOPMENT; } /** The type of build, like "user" or "eng". */ diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl index 3cde0319efd3..e5de3e157c88 100644 --- a/core/java/android/os/IUserManager.aidl +++ b/core/java/android/os/IUserManager.aidl @@ -131,4 +131,5 @@ interface IUserManager { String getUserName(); long getUserStartRealtime(); long getUserUnlockRealtime(); + boolean setUserEphemeral(int userId, boolean enableEphemeral); } diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index e06e7326a860..14082f3388a0 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -213,12 +213,6 @@ public class Process { public static final int SE_UID = 1068; /** - * Defines the UID/GID for the iorapd. - * @hide - */ - public static final int IORAPD_UID = 1071; - - /** * Defines the UID/GID for the NetworkStack app. * @hide */ diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index a64e63eacd56..570d533ccf1e 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -1997,13 +1997,22 @@ public class UserManager { * @return Whether guest user is always ephemeral * @hide */ - @TestApi - public static boolean isGuestUserEphemeral() { + public static boolean isGuestUserAlwaysEphemeral() { return Resources.getSystem() .getBoolean(com.android.internal.R.bool.config_guestUserEphemeral); } /** + * @return true, when we want to enable user manager API and UX to allow + * guest user ephemeral state change based on user input + * @hide + */ + public static boolean isGuestUserAllowEphemeralStateChange() { + return Resources.getSystem() + .getBoolean(com.android.internal.R.bool.config_guestUserAllowEphemeralStateChange); + } + + /** * Checks whether the device is running in a headless system user mode. * * <p>Headless system user mode means the {@link #isSystemUser() system user} runs system @@ -3424,6 +3433,20 @@ public class UserManager { if (guest != null) { Settings.Secure.putStringForUser(context.getContentResolver(), Settings.Secure.SKIP_FIRST_USE_HINTS, "1", guest.id); + + if (UserManager.isGuestUserAllowEphemeralStateChange()) { + // Mark guest as (changeably) ephemeral if REMOVE_GUEST_ON_EXIT is 1 + // This is done so that a user via a UI controller can choose to + // make a guest as ephemeral or not. + // Settings.Global.REMOVE_GUEST_ON_EXIT holds the choice on what the guest state + // should be, with default being ephemeral. + boolean resetGuestOnExit = Settings.Global.getInt(context.getContentResolver(), + Settings.Global.REMOVE_GUEST_ON_EXIT, 1) == 1; + + if (resetGuestOnExit && !guest.isEphemeral()) { + setUserEphemeral(guest.id, true); + } + } } return guest; } catch (ServiceSpecificException e) { @@ -4941,6 +4964,31 @@ public class UserManager { } /** + * Set the user as ephemeral or non-ephemeral. + * + * If the user was initially created as ephemeral then this + * method has no effect and false is returned. + * + * @param userId the user's integer id + * @param enableEphemeral true: change user state to ephemeral, + * false: change user state to non-ephemeral + * @return true: user now has the desired ephemeral state, + * false: desired user ephemeral state could not be set + * + * @hide + */ + @RequiresPermission(anyOf = { + android.Manifest.permission.MANAGE_USERS, + android.Manifest.permission.CREATE_USERS}) + public boolean setUserEphemeral(@UserIdInt int userId, boolean enableEphemeral) { + try { + return mService.setUserEphemeral(userId, enableEphemeral); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + + /** * Updates the context user's name. * * @param name the new name for the user diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java index ec1c57d675c1..237f6ed819f6 100644 --- a/core/java/android/os/VibrationEffect.java +++ b/core/java/android/os/VibrationEffect.java @@ -413,10 +413,8 @@ public abstract class VibrationEffect implements Parcelable { * {@link #startWaveform(VibrationEffect.VibrationParameter)}. * * @see VibrationEffect.WaveformBuilder - * @hide */ @NonNull - @TestApi public static WaveformBuilder startWaveform() { return new WaveformBuilder(); } @@ -433,10 +431,8 @@ public abstract class VibrationEffect implements Parcelable { * @return The {@link VibrationEffect.WaveformBuilder} started with the initial parameters. * * @see VibrationEffect.WaveformBuilder - * @hide */ @NonNull - @TestApi public static WaveformBuilder startWaveform(@NonNull VibrationParameter initialParameter) { WaveformBuilder builder = startWaveform(); builder.addTransition(Duration.ZERO, initialParameter); @@ -458,10 +454,8 @@ public abstract class VibrationEffect implements Parcelable { * @return The {@link VibrationEffect.WaveformBuilder} started with the initial parameters. * * @see VibrationEffect.WaveformBuilder - * @hide */ @NonNull - @TestApi public static WaveformBuilder startWaveform(@NonNull VibrationParameter initialParameter1, @NonNull VibrationParameter initialParameter2) { WaveformBuilder builder = startWaveform(); @@ -875,9 +869,7 @@ public abstract class VibrationEffect implements Parcelable { /** * Exception thrown when adding an element to a {@link Composition} that already ends in an * indefinitely repeating effect. - * @hide */ - @TestApi public static final class UnreachableAfterRepeatingIndefinitelyException extends IllegalStateException { UnreachableAfterRepeatingIndefinitelyException() { @@ -946,10 +938,8 @@ public abstract class VibrationEffect implements Parcelable { * * @throws UnreachableAfterRepeatingIndefinitelyException if the composition is currently * ending with a repeating effect. - * @hide */ @NonNull - @TestApi public Composition addOffDuration(@NonNull Duration duration) { int durationMs = (int) duration.toMillis(); Preconditions.checkArgumentNonnegative(durationMs, "Off period must be non-negative"); @@ -975,10 +965,8 @@ public abstract class VibrationEffect implements Parcelable { * * @throws UnreachableAfterRepeatingIndefinitelyException if the composition is currently * ending with a repeating effect. - * @hide */ @NonNull - @TestApi public Composition addEffect(@NonNull VibrationEffect effect) { return addSegments(effect); } @@ -999,10 +987,8 @@ public abstract class VibrationEffect implements Parcelable { * @throws IllegalArgumentException if the given effect is already repeating indefinitely. * @throws UnreachableAfterRepeatingIndefinitelyException if the composition is currently * ending with a repeating effect. - * @hide */ @NonNull - @TestApi public Composition repeatEffectIndefinitely(@NonNull VibrationEffect effect) { Preconditions.checkArgument(effect.getDuration() < Long.MAX_VALUE, "Can't repeat an indefinitely repeating effect. Consider addEffect instead."); @@ -1216,9 +1202,7 @@ public abstract class VibrationEffect implements Parcelable { * .build();}</pre> * * @see VibrationEffect#startWaveform - * @hide */ - @TestApi public static final class WaveformBuilder { // Epsilon used for float comparison of amplitude and frequency values on transitions. private static final float EPSILON = 1e-5f; @@ -1399,10 +1383,8 @@ public abstract class VibrationEffect implements Parcelable { * <p>Examples of concrete parameters are the vibration amplitude or frequency. * * @see VibrationEffect.WaveformBuilder - * @hide */ @SuppressWarnings("UserHandleName") // This is not a regular set of parameters, no *Params. - @TestApi public static class VibrationParameter { VibrationParameter() { } diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java index 465d90d36698..7f0d6349f57f 100644 --- a/core/java/android/os/Vibrator.java +++ b/core/java/android/os/Vibrator.java @@ -212,9 +212,7 @@ public abstract class Vibrator { * * @return True if the hardware can control the frequency of the vibrations independently of * the vibration amplitude, false otherwise. - * @hide */ - @TestApi public boolean hasFrequencyControl() { // We currently can only control frequency of the vibration using the compose PWLE method. return getInfo().hasCapability( @@ -238,9 +236,7 @@ public abstract class Vibrator { * @return the resonant frequency of the vibrator, or {@link Float#NaN NaN} if it's unknown, not * applicable, or if this vibrator is a composite of multiple physical devices with different * frequencies. - * @hide */ - @TestApi public float getResonantFrequency() { return getInfo().getResonantFrequencyHz(); } @@ -251,9 +247,7 @@ public abstract class Vibrator { * @return the Q factor of the vibrator, or {@link Float#NaN NaN} if it's unknown, not * applicable, or if this vibrator is a composite of multiple physical devices with different * Q factors. - * @hide */ - @TestApi public float getQFactor() { return getInfo().getQFactor(); } @@ -268,9 +262,7 @@ public abstract class Vibrator { * frequency control. If this vibrator is a composite of multiple physical devices then this * will return a profile supported in all devices, or null if the intersection is empty or not * available. - * @hide */ - @TestApi @Nullable public VibratorFrequencyProfile getFrequencyProfile() { VibratorInfo.FrequencyProfile frequencyProfile = getInfo().getFrequencyProfile(); diff --git a/core/java/android/os/vibrator/VibratorFrequencyProfile.java b/core/java/android/os/vibrator/VibratorFrequencyProfile.java index afc0007afd42..0f2aa157d94c 100644 --- a/core/java/android/os/vibrator/VibratorFrequencyProfile.java +++ b/core/java/android/os/vibrator/VibratorFrequencyProfile.java @@ -18,7 +18,6 @@ package android.os.vibrator; import android.annotation.FloatRange; import android.annotation.NonNull; -import android.annotation.TestApi; import android.os.VibratorInfo; import com.android.internal.util.Preconditions; @@ -39,9 +38,7 @@ import com.android.internal.util.Preconditions; * frequency increment between each pair of amplitude values. * * <p>Vibrators without independent frequency control do not have a frequency profile. - * @hide */ -@TestApi public final class VibratorFrequencyProfile { private final VibratorInfo.FrequencyProfile mFrequencyProfile; diff --git a/core/java/android/permission/Permissions.md b/core/java/android/permission/Permissions.md index dfe748b09464..e61ecd8781d0 100644 --- a/core/java/android/permission/Permissions.md +++ b/core/java/android/permission/Permissions.md @@ -71,9 +71,9 @@ Any app can request any permission via adding an entry in the manifest file like A requested permission does not necessarily mean that the permission is granted. When and how a permission is granted depends on the protection level of the permission. If no protection level is -set, the permission will always be granted. Such "normal" permissions can still be useful as it -will be easy to find apps using a certain functionality on app stores and by checking `dumpsys -package`. +set, it will default to `normal` and the permission will always be granted if requested. Such +`normal` permissions can still be useful as it will be easy to find apps using a certain +functionality on app stores and by checking `dumpsys package`. #### Checking a permission @@ -686,17 +686,37 @@ able to call APIs not available to other apps. This is implemented by granting p these system apps and then enforcing the permissions in the API similar to other [install time permissions](#checking-a-permission). -System apps are not different from regular apps, but the protection levels (e.g. +System apps are not different from regular apps, but the protection flags (e.g. [privileged](#privileged-permissions), [preinstalled](#preinstalled-permissions)) mentioned in this section are more commonly used by system apps. -### Multiple permission levels +### Permission protection level -It is possible to assign multiple protection levels to a permission. Very common combinations are -for example adding `signature` to all permissions to make sure the platform signed apps can be -granted the permission, e.g. `privileged|signature`. +Every permission has a protection level (`android:protectionlevel`), which is a combination of one +required protection (`PermissionInfo.getProtection()`) and multiple optional protection flags +(`PermissionInfo.getProtectionFlags()`). -The permission will be granted if the app qualifies for _any_ of the permission levels. +The protection can be one of the following: + +- [`normal`](#requesting-a-permission): The permission will be granted to apps requesting it in +their manifest. +- [`dangerous`](#runtime-permissions): The permission will be a runtime permission. +- [`signature`](#signature-permissions): The permission will be granted to apps being signed with +the same certificate as the app defining the permission. If the permission is a platform permission, +it means those apps need to be platform-signed. +- `internal`: This is a no-op protection so that it won't allow granting the permission by itself. +However, it will be useful when defining permissions that should only be granted according to its +protection flags, e.g. `internal|role` for a role-only permission. + +There are various optional protection flags that can be added to protection level, in addition to +the required protection, e.g. [appop](#app_op-permissions), +[preinstalled](#preinstalled-permissions), [privileged](#privileged-permissions), +[installer](#limited-permissions), [role](#role-protected-permissions) and +[development](#development-permissions). + +The permission will be granted to an app if it meets _any_ of the protection or protection flags (an +`OR` relationship). For example, `signature|privileged` allows the permission to be granted to +platform-signed apps as well as privileged apps. ### App-op permissions @@ -716,18 +736,15 @@ and special behavior. Hence this section is a guideline, not a rule. #### Defining an app-op permission Only the platform can reasonably define an app-op permission. The permission is defined in the -platforms manifest using the `appop` protection level +platforms manifest using the `appop` protection flag: ```xml <manifest package="android"> <permission android:name="android.permission.MY_APPOP_PERMISSION" - android:protectionLevel="appop|signature" /> + android:protectionLevel="signature|appop" /> </manifest> ``` -Almost always the protection level is app-op | something else, like -[signature](#signature-permissions) (in the case above) or [privileged](#privileged-permissions). - #### Checking an app-op permission The `PermissionChecker` utility can check app-op permissions with the [same syntax as runtime @@ -913,12 +930,12 @@ See > Not recommended -By adding the `development` protection level to any permissions the permission can be granted via +By adding the `development` protection flag to any permissions the permission can be granted via the `pm grant` shell command. This appears to be useful for development and testing, but it is very highly discouraged. Any user can grant them permanently via adb, hence adding this tag removes all guarantees the permission might otherwise provide. -### Other protection levels +### Other protection flags There are other levels (such as `runtime`) but they are for special purposes on should not be used by platform developers. diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 9d166b995e4f..6a19ecb960da 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -9682,6 +9682,13 @@ public final class Settings { "biometric_debug_enabled"; /** + * Whether or not virtual sensors are enabled. + * @hide + */ + @Readable + public static final String BIOMETRIC_VIRTUAL_ENABLED = "biometric_virtual_enabled"; + + /** * Whether or not biometric is allowed on Keyguard. * @hide */ @@ -10921,6 +10928,14 @@ public final class Settings { public static final String ADD_USERS_WHEN_LOCKED = "add_users_when_locked"; /** + * Whether guest user should be removed on exit from guest mode. + * <p> + * Type: int + * @hide + */ + public static final String REMOVE_GUEST_ON_EXIT = "remove_guest_on_exit"; + + /** * Whether applying ramping ringer on incoming phone call ringtone. * <p>1 = apply ramping ringer * <p>0 = do not apply ramping ringer @@ -17265,6 +17280,12 @@ public final class Settings { public static final String AMBIENT_TILT_TO_BRIGHT = "ambient_tilt_to_bright"; /** + * Whether touch and hold to edit WF is enabled + * @hide + */ + public static final String TOUCH_AND_HOLD_WATCH_FACE = "touch_and_hold_watchface"; + + /** * Whether the current watchface is decomposable. * @hide */ @@ -17482,6 +17503,18 @@ public final class Settings { * @hide */ public static final String WET_MODE_ON = "wet_mode_on"; + + /* + * Whether the screen-unlock (keyguard) sound is enabled. + * @hide + */ + public static final String SCREEN_UNLOCK_SOUND_ENABLED = "screen_unlock_sound_enabled"; + + /* + * Whether charging sounds are enabled. + * @hide + */ + public static final String CHARGING_SOUNDS_ENABLED = "charging_sounds_enabled"; } } diff --git a/core/java/android/security/attestationverification/AttestationVerificationManager.java b/core/java/android/security/attestationverification/AttestationVerificationManager.java index db783ceabcdb..2e61db1b932a 100644 --- a/core/java/android/security/attestationverification/AttestationVerificationManager.java +++ b/core/java/android/security/attestationverification/AttestationVerificationManager.java @@ -226,10 +226,10 @@ public class AttestationVerificationManager { public static final int PROFILE_SELF_TRUSTED = 2; /** - * A system-defined profile which verifies that the attesting environment environment is similar - * to the current device in terms of security model and security configuration. This category is - * fairly broad and most securely configured Android devices should qualify, along with a - * variety of non-Android devices. + * A system-defined profile which verifies that the attesting environment is similar to the + * current device in terms of security model and security configuration. This category is fairly + * broad and most securely configured Android devices should qualify, along with a variety of + * non-Android devices. */ public static final int PROFILE_PEER_DEVICE = 3; @@ -321,4 +321,52 @@ public class AttestationVerificationManager { /** Requirements bundle parameter for a challenge. */ public static final String PARAM_CHALLENGE = "localbinding.challenge"; + + /** @hide */ + public static String localBindingTypeToString(@LocalBindingType int localBindingType) { + final String text; + switch (localBindingType) { + case TYPE_UNKNOWN: + text = "UNKNOWN"; + break; + + case TYPE_APP_DEFINED: + text = "APP_DEFINED"; + break; + + case TYPE_PUBLIC_KEY: + text = "PUBLIC_KEY"; + break; + + case TYPE_CHALLENGE: + text = "CHALLENGE"; + break; + + default: + return Integer.toString(localBindingType); + } + return text + "(" + localBindingType + ")"; + } + + /** @hide */ + public static String verificationResultCodeToString(@VerificationResult int resultCode) { + final String text; + switch (resultCode) { + case RESULT_UNKNOWN: + text = "UNKNOWN"; + break; + + case RESULT_SUCCESS: + text = "SUCCESS"; + break; + + case RESULT_FAILURE: + text = "FAILURE"; + break; + + default: + return Integer.toString(resultCode); + } + return text + "(" + resultCode + ")"; + } } diff --git a/core/java/android/service/autofill/FillContext.java b/core/java/android/service/autofill/FillContext.java index 8331550a7ef5..cc1b6cda82bb 100644 --- a/core/java/android/service/autofill/FillContext.java +++ b/core/java/android/service/autofill/FillContext.java @@ -32,7 +32,7 @@ import android.view.autofill.AutofillId; import com.android.internal.util.DataClass; -import java.util.LinkedList; +import java.util.ArrayDeque; /** * This class represents a context for each fill request made via {@link @@ -95,7 +95,7 @@ public final class FillContext implements Parcelable { * @hide */ @NonNull public ViewNode[] findViewNodesByAutofillIds(@NonNull AutofillId[] ids) { - final LinkedList<ViewNode> nodesToProcess = new LinkedList<>(); + final ArrayDeque<ViewNode> nodesToProcess = new ArrayDeque<>(); final ViewNode[] foundNodes = new AssistStructure.ViewNode[ids.length]; // Indexes of foundNodes that are not found yet diff --git a/core/java/android/service/autofill/FillRequest.java b/core/java/android/service/autofill/FillRequest.java index 1507c87c0452..327cda3360bb 100644 --- a/core/java/android/service/autofill/FillRequest.java +++ b/core/java/android/service/autofill/FillRequest.java @@ -97,7 +97,7 @@ public final class FillRequest implements Parcelable { */ public static final @RequestFlags int FLAG_VIEW_NOT_FOCUSED = 0x10; - // The flag value 0x20 has been used. + // The flag value 0x20 has been defined in AutofillManager. /** * Indicates the request supports fill dialog presentation for the fields, the diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java index b9e60a11a8f3..acefebc232ae 100644 --- a/core/java/android/service/notification/NotificationListenerService.java +++ b/core/java/android/service/notification/NotificationListenerService.java @@ -258,6 +258,8 @@ public abstract class NotificationListenerService extends Service { public static final int REASON_CLEAR_DATA = 21; /** Notification was canceled due to an assistant adjustment update. */ public static final int REASON_ASSISTANT_CANCEL = 22; + /** Notification was canceled when lockdown mode is enabled. */ + public static final int REASON_LOCKDOWN = 23; /** * @hide @@ -285,6 +287,7 @@ public abstract class NotificationListenerService extends Service { REASON_CHANNEL_REMOVED, REASON_CLEAR_DATA, REASON_ASSISTANT_CANCEL, + REASON_LOCKDOWN, }) public @interface NotificationCancelReason{}; diff --git a/core/java/android/service/quickaccesswallet/QuickAccessWalletServiceInfo.java b/core/java/android/service/quickaccesswallet/QuickAccessWalletServiceInfo.java index 0d290eee5777..ce38bb823fb3 100644 --- a/core/java/android/service/quickaccesswallet/QuickAccessWalletServiceInfo.java +++ b/core/java/android/service/quickaccesswallet/QuickAccessWalletServiceInfo.java @@ -135,7 +135,7 @@ class QuickAccessWalletServiceInfo { return null; } - private static class ServiceMetadata { + static class ServiceMetadata { @Nullable private final String mSettingsActivity; @Nullable @@ -161,7 +161,7 @@ class QuickAccessWalletServiceInfo { } } - private static ServiceMetadata parseServiceMetadata(Context context, ServiceInfo serviceInfo) { + static ServiceMetadata parseServiceMetadata(Context context, ServiceInfo serviceInfo) { PackageManager pm = context.getPackageManager(); final XmlResourceParser parser = serviceInfo.loadXmlMetaData(pm, QuickAccessWalletService.SERVICE_META_DATA); diff --git a/core/java/android/service/voice/AbstractHotwordDetector.java b/core/java/android/service/voice/AbstractHotwordDetector.java index 01d5638461af..5b3b78b65786 100644 --- a/core/java/android/service/voice/AbstractHotwordDetector.java +++ b/core/java/android/service/voice/AbstractHotwordDetector.java @@ -22,6 +22,7 @@ import android.annotation.CallSuper; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityThread; +import android.app.compat.CompatChanges; import android.media.AudioFormat; import android.media.permission.Identity; import android.os.Handler; @@ -65,6 +66,13 @@ abstract class AbstractHotwordDetector implements HotwordDetector { } /** + * Method to be called for the detector to ready/register itself with underlying system + * services. + */ + abstract void initialize(@Nullable PersistableBundle options, + @Nullable SharedMemory sharedMemory); + + /** * Detect hotword from an externally supplied stream of data. * * @return true if the request to start recognition succeeded @@ -73,7 +81,7 @@ abstract class AbstractHotwordDetector implements HotwordDetector { public boolean startRecognition( @NonNull ParcelFileDescriptor audioStream, @NonNull AudioFormat audioFormat, - @Nullable PersistableBundle options) { + @Nullable PersistableBundle options) throws IllegalDetectorStateException { if (DEBUG) { Slog.i(TAG, "#recognizeHotword"); } @@ -98,19 +106,22 @@ abstract class AbstractHotwordDetector implements HotwordDetector { * Set configuration and pass read-only data to hotword detection service. * * @param options Application configuration data to provide to the - * {@link HotwordDetectionService}. PersistableBundle does not allow any remotable objects or - * other contents that can be used to communicate with other processes. + * {@link HotwordDetectionService}. PersistableBundle does not allow any remotable + * objects or other contents that can be used to communicate with other processes. * @param sharedMemory The unrestricted data blob to provide to the - * {@link HotwordDetectionService}. Use this to provide the hotword models data or other - * such data to the trusted process. - * - * @throws IllegalStateException if this AlwaysOnHotwordDetector wasn't specified to use a - * {@link HotwordDetectionService} when it was created. In addition, if this - * AlwaysOnHotwordDetector is in an invalid or error state. + * {@link HotwordDetectionService}. Use this to provide the hotword models data or other + * such data to the trusted process. + * @throws IllegalDetectorStateException Thrown when a caller has a target SDK of + * Android Tiramisu or above and attempts to start a recognition when the detector is + * not able based on the state. Because the caller receives updates via an asynchronous + * callback and the state of the detector can change without caller's knowledge, a + * checked exception is thrown. + * @throws IllegalStateException if this HotwordDetector wasn't specified to use a + * {@link HotwordDetectionService} when it was created. */ @Override public void updateState(@Nullable PersistableBundle options, - @Nullable SharedMemory sharedMemory) { + @Nullable SharedMemory sharedMemory) throws IllegalDetectorStateException { if (DEBUG) { Slog.d(TAG, "updateState()"); } @@ -156,9 +167,13 @@ abstract class AbstractHotwordDetector implements HotwordDetector { } } - protected void throwIfDetectorIsNoLongerActive() { + protected void throwIfDetectorIsNoLongerActive() throws IllegalDetectorStateException { if (!mIsDetectorActive.get()) { Slog.e(TAG, "attempting to use a destroyed detector which is no longer active"); + if (CompatChanges.isChangeEnabled(HOTWORD_DETECTOR_THROW_CHECKED_EXCEPTION)) { + throw new IllegalDetectorStateException( + "attempting to use a destroyed detector which is no longer active"); + } throw new IllegalStateException( "attempting to use a destroyed detector which is no longer active"); } diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java index bc42da6b4c97..d01e7feba36e 100644 --- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java +++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java @@ -18,6 +18,7 @@ package android.service.voice; import static android.Manifest.permission.CAPTURE_AUDIO_HOTWORD; import static android.Manifest.permission.RECORD_AUDIO; +import static android.service.voice.VoiceInteractionService.MULTIPLE_ACTIVE_HOTWORD_DETECTORS; import android.annotation.IntDef; import android.annotation.NonNull; @@ -27,6 +28,7 @@ import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.TestApi; import android.app.ActivityThread; +import android.app.compat.CompatChanges; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.Intent; @@ -50,9 +52,11 @@ import android.os.ParcelFileDescriptor; import android.os.PersistableBundle; import android.os.RemoteException; import android.os.SharedMemory; +import android.text.TextUtils; import android.util.Log; import android.util.Slog; +import com.android.internal.annotations.GuardedBy; import com.android.internal.app.IHotwordRecognitionStatusCallback; import com.android.internal.app.IVoiceInteractionManagerService; import com.android.internal.app.IVoiceInteractionSoundTriggerSession; @@ -62,8 +66,11 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Locale; +import java.util.Objects; +import java.util.Set; /** * A class that lets a VoiceInteractionService implementation interact with @@ -275,11 +282,12 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { * The metadata of the Keyphrase, derived from the enrollment application. * This may be null if this keyphrase isn't supported by the enrollment application. */ + @GuardedBy("mLock") @Nullable private KeyphraseMetadata mKeyphraseMetadata; private final KeyphraseEnrollmentInfo mKeyphraseEnrollmentInfo; private final IVoiceInteractionManagerService mModelManagementService; - private final IVoiceInteractionSoundTriggerSession mSoundTriggerSession; + private IVoiceInteractionSoundTriggerSession mSoundTriggerSession; private final SoundTriggerListener mInternalCallback; private final Callback mExternalCallback; private final Handler mHandler; @@ -287,6 +295,9 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { private final int mTargetSdkVersion; private final boolean mSupportHotwordDetectionService; + @GuardedBy("mLock") + private boolean mIsAvailabilityOverriddenByTestApi = false; + @GuardedBy("mLock") private int mAvailability = STATE_NOT_READY; /** @@ -788,8 +799,7 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { public AlwaysOnHotwordDetector(String text, Locale locale, Callback callback, KeyphraseEnrollmentInfo keyphraseEnrollmentInfo, IVoiceInteractionManagerService modelManagementService, int targetSdkVersion, - boolean supportHotwordDetectionService, @Nullable PersistableBundle options, - @Nullable SharedMemory sharedMemory) { + boolean supportHotwordDetectionService) { super(modelManagementService, callback, supportHotwordDetectionService ? DETECTOR_TYPE_TRUSTED_HOTWORD_DSP : DETECTOR_TYPE_NORMAL); @@ -803,6 +813,12 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { mModelManagementService = modelManagementService; mTargetSdkVersion = targetSdkVersion; mSupportHotwordDetectionService = supportHotwordDetectionService; + } + + @Override + void initialize(@Nullable PersistableBundle options, @Nullable SharedMemory sharedMemory) { + // TODO: transition to use an API that is not updateState to provide + // onHotwordDetectionServiceInitialized status to external callback if (mSupportHotwordDetectionService) { updateStateLocked(options, sharedMemory, mInternalCallback, DETECTOR_TYPE_TRUSTED_HOTWORD_DSP); @@ -810,30 +826,40 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { try { Identity identity = new Identity(); identity.packageName = ActivityThread.currentOpPackageName(); - mSoundTriggerSession = mModelManagementService.createSoundTriggerSessionAsOriginator( - identity, mBinder); + mSoundTriggerSession = + mModelManagementService.createSoundTriggerSessionAsOriginator( + identity, mBinder); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } - new RefreshAvailabiltyTask().execute(); + new RefreshAvailabilityTask().execute(); } /** * {@inheritDoc} * - * @throws IllegalStateException if this AlwaysOnHotwordDetector wasn't specified to use a - * {@link HotwordDetectionService} when it was created. In addition, if this - * AlwaysOnHotwordDetector is in an invalid or error state. + * @throws IllegalDetectorStateException Thrown when a caller has a target SDK of API level 33 + * or above and this AlwaysOnHotwordDetector wasn't specified to use a + * {@link HotwordDetectionService} when it was created. In addition, the exception can + * be thrown if this AlwaysOnHotwordDetector is in an invalid or error state. + * @throws IllegalStateException Thrown when a caller has a target SDK below API level 33 if + * this AlwaysOnHotwordDetector wasn't specified to use a + * {@link HotwordDetectionService} when it was created. In addition, the exception can + * be thrown if this AlwaysOnHotwordDetector is in an invalid or error state. */ @Override public final void updateState(@Nullable PersistableBundle options, - @Nullable SharedMemory sharedMemory) { + @Nullable SharedMemory sharedMemory) throws IllegalDetectorStateException { synchronized (mLock) { if (!mSupportHotwordDetectionService) { throw new IllegalStateException( "updateState called, but it doesn't support hotword detection service"); } if (mAvailability == STATE_INVALID || mAvailability == STATE_ERROR) { + if (CompatChanges.isChangeEnabled(HOTWORD_DETECTOR_THROW_CHECKED_EXCEPTION)) { + throw new IllegalDetectorStateException( + "updateState called on an invalid detector or error state"); + } throw new IllegalStateException( "updateState called on an invalid detector or error state"); } @@ -843,6 +869,48 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { } /** + * Test API for manipulating the voice engine and sound model availability. + * + * After overriding the availability status, the client's + * {@link Callback#onAvailabilityChanged(int)} will be called to reflect the updated state. + * + * When this override is set, all system updates to availability will be ignored. + * @hide + */ + @TestApi + public void overrideAvailability(int availability) { + synchronized (mLock) { + // ENROLLED state requires there to be metadata about the sound model so a fake one + // is created. + if (mKeyphraseMetadata == null && availability == STATE_KEYPHRASE_ENROLLED) { + Set<Locale> fakeSupportedLocales = new HashSet<>(); + fakeSupportedLocales.add(mLocale); + mKeyphraseMetadata = new KeyphraseMetadata(1, mText, fakeSupportedLocales, + AlwaysOnHotwordDetector.RECOGNITION_MODE_VOICE_TRIGGER); + } + + mAvailability = availability; + mIsAvailabilityOverriddenByTestApi = true; + notifyStateChangedLocked(); + } + } + + /** + * Test API for clearing an availability override set by {@link #overrideAvailability(int)} + * + * This method will restore the availability to the current system state. + * @hide + */ + @TestApi + public void resetAvailability() { + synchronized (mLock) { + mIsAvailabilityOverriddenByTestApi = false; + } + // Execute a refresh availability task - which should then notify of a change. + new RefreshAvailabilityTask().execute(); + } + + /** * Test API to simulate to trigger hardware recognition event for test. * * @hide @@ -878,28 +946,46 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { * @see #RECOGNITION_MODE_USER_IDENTIFICATION * @see #RECOGNITION_MODE_VOICE_TRIGGER * - * @throws UnsupportedOperationException if the keyphrase itself isn't supported. - * Callers should only call this method after a supported state callback on - * {@link Callback#onAvailabilityChanged(int)} to avoid this exception. - * @throws IllegalStateException if the detector is in an invalid or error state. - * This may happen if another detector has been instantiated or the - * {@link VoiceInteractionService} hosting this detector has been shut down. + * @throws IllegalDetectorStateException Thrown when a caller has a target SDK of API level 33 + * or above. Because the caller receives availability updates via an asynchronous + * callback, it may be due to the availability changing while this call is performed. + * - Throws if the detector is in an invalid or error state. + * This may happen if another detector has been instantiated or the + * {@link VoiceInteractionService} hosting this detector has been shut down. + * @throws UnsupportedOperationException Thrown when a caller has a target SDK below API level + * 33 Android if the recognition isn't supported. Callers should only call this method + * after a supported state callback on {@link Callback#onAvailabilityChanged(int)} to + * avoid this exception. + * @throws IllegalStateException Thrown when a caller has a target SDK below Android API level + * 33 if the detector is in an invalid or error state. This may happen if another + * detector has been instantiated or the {@link VoiceInteractionService} hosting this + * detector has been shut down. */ - public @RecognitionModes int getSupportedRecognitionModes() { + public @RecognitionModes + int getSupportedRecognitionModes() throws IllegalDetectorStateException { if (DBG) Slog.d(TAG, "getSupportedRecognitionModes()"); synchronized (mLock) { return getSupportedRecognitionModesLocked(); } } - private int getSupportedRecognitionModesLocked() { + @GuardedBy("mLock") + private int getSupportedRecognitionModesLocked() throws IllegalDetectorStateException { if (mAvailability == STATE_INVALID || mAvailability == STATE_ERROR) { + if (CompatChanges.isChangeEnabled(HOTWORD_DETECTOR_THROW_CHECKED_EXCEPTION)) { + throw new IllegalDetectorStateException("getSupportedRecognitionModes called on an" + + " invalid detector or error state"); + } throw new IllegalStateException( "getSupportedRecognitionModes called on an invalid detector or error state"); } // This method only makes sense if we can actually support a recognition. if (mAvailability != STATE_KEYPHRASE_ENROLLED || mKeyphraseMetadata == null) { + if (CompatChanges.isChangeEnabled(HOTWORD_DETECTOR_THROW_CHECKED_EXCEPTION)) { + throw new IllegalDetectorStateException("Getting supported recognition modes for" + + " the keyphrase is not supported"); + } throw new UnsupportedOperationException( "Getting supported recognition modes for the keyphrase is not supported"); } @@ -926,6 +1012,7 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { } } + @GuardedBy("mLock") private int getSupportedAudioCapabilitiesLocked() { try { ModuleProperties properties = @@ -949,30 +1036,77 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { * @see #RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS * * @param recognitionFlags The flags to control the recognition properties. + * @param data Additional pass-through data to the system voice engine along with the + * startRecognition request. This data is intended to provide additional parameters + * when starting the opaque sound model. * @return Indicates whether the call succeeded or not. - * @throws UnsupportedOperationException if the recognition isn't supported. - * Callers should only call this method after a supported state callback on - * {@link Callback#onAvailabilityChanged(int)} to avoid this exception. - * @throws IllegalStateException if the detector is in an invalid or error state. - * This may happen if another detector has been instantiated or the - * {@link VoiceInteractionService} hosting this detector has been shut down. + * @throws IllegalDetectorStateException Thrown when a caller has a target SDK of API level 33 + * or above and attempts to start a recognition when the detector is not able based on + * the availability state. This can be thrown even if the state has been checked before + * calling this method because the caller receives availability updates via an + * asynchronous callback, it may be due to the availability changing while this call is + * performed. + * - Throws if the recognition isn't supported. + * Callers should only call this method after a supported state callback on + * {@link Callback#onAvailabilityChanged(int)} to avoid this exception. + * - Also throws if the detector is in an invalid or error state. + * This may happen if another detector has been instantiated or the + * {@link VoiceInteractionService} hosting this detector has been shut down. + * @throws UnsupportedOperationException Thrown when a caller has a target SDK below API level + * 33 Android if the recognition isn't supported. Callers should only call this method + * after a supported state callback on {@link Callback#onAvailabilityChanged(int)} to + * avoid this exception. + * @throws IllegalStateException Thrown when a caller has a target SDK below Android API level + * 33 if the detector is in an invalid or error state. This may happen if another + * detector has been instantiated or the {@link VoiceInteractionService} hosting this + * detector has been shut down. */ @RequiresPermission(allOf = {RECORD_AUDIO, CAPTURE_AUDIO_HOTWORD}) - public boolean startRecognition(@RecognitionFlags int recognitionFlags) { - if (DBG) Slog.d(TAG, "startRecognition(" + recognitionFlags + ")"); + public boolean startRecognition(@RecognitionFlags int recognitionFlags, @NonNull byte[] data) + throws IllegalDetectorStateException { synchronized (mLock) { - if (mAvailability == STATE_INVALID || mAvailability == STATE_ERROR) { - throw new IllegalStateException( - "startRecognition called on an invalid detector or error state"); - } - - // Check if we can start/stop a recognition. - if (mAvailability != STATE_KEYPHRASE_ENROLLED) { - throw new UnsupportedOperationException( - "Recognition for the given keyphrase is not supported"); - } + return startRecognitionLocked(recognitionFlags, data) + == STATUS_OK; + } + } - return startRecognitionLocked(recognitionFlags) == STATUS_OK; + /** + * Starts recognition for the associated keyphrase. + * Caller must be the active voice interaction service via + * Settings.Secure.VOICE_INTERACTION_SERVICE. + * + * @see #RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO + * @see #RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS + * + * @param recognitionFlags The flags to control the recognition properties. + * @return Indicates whether the call succeeded or not. + * @throws IllegalDetectorStateException Thrown when a caller has a target SDK of API level 33 + * or above and attempts to start a recognition when the detector is not able based on + * the availability state. This can be thrown even if the state has been checked before + * calling this method because the caller receives availability updates via an + * asynchronous callback, it may be due to the availability changing while this call is + * performed. + * - Throws if the recognition isn't supported. + * Callers should only call this method after a supported state callback on + * {@link Callback#onAvailabilityChanged(int)} to avoid this exception. + * - Also throws if the detector is in an invalid or error state. + * This may happen if another detector has been instantiated or the + * {@link VoiceInteractionService} hosting this detector has been shut down. + * @throws UnsupportedOperationException Thrown when a caller has a target SDK below API level + * 33 if the recognition isn't supported. Callers should only call this method after a + * supported state callback on {@link Callback#onAvailabilityChanged(int)} to avoid this + * exception. + * @throws IllegalStateException Thrown when a caller has a target SDK below API level 33 if the + * detector is in an invalid or error state. This may happen if another detector has + * been instantiated or the {@link VoiceInteractionService} hosting this detector has + * been shut down. + */ + @RequiresPermission(allOf = {RECORD_AUDIO, CAPTURE_AUDIO_HOTWORD}) + public boolean startRecognition(@RecognitionFlags int recognitionFlags) + throws IllegalDetectorStateException { + if (DBG) Slog.d(TAG, "startRecognition(" + recognitionFlags + ")"); + synchronized (mLock) { + return startRecognitionLocked(recognitionFlags, null /* data */) == STATUS_OK; } } @@ -983,7 +1117,8 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { */ @RequiresPermission(allOf = {RECORD_AUDIO, CAPTURE_AUDIO_HOTWORD}) @Override - public boolean startRecognition() { + public boolean startRecognition() + throws IllegalDetectorStateException { return startRecognition(0); } @@ -993,28 +1128,44 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { * Settings.Secure.VOICE_INTERACTION_SERVICE. * * @return Indicates whether the call succeeded or not. - * @throws UnsupportedOperationException if the recognition isn't supported. - * Callers should only call this method after a supported state callback on - * {@link Callback#onAvailabilityChanged(int)} to avoid this exception. - * @throws IllegalStateException if the detector is in an invalid or error state. - * This may happen if another detector has been instantiated or the - * {@link VoiceInteractionService} hosting this detector has been shut down. + * @throws IllegalDetectorStateException Thrown when a caller has a target SDK of + * API level 33 or above and attempts to stop a recognition when the detector is + * not able based on the state. This can be thrown even if the state has been checked + * before calling this method because the caller receives availability updates via an + * asynchronous callback, it may be due to the availability changing while this call is + * performed. + * @throws UnsupportedOperationException Thrown when a caller has a target SDK below API level + * 33 if the recognition isn't supported. Callers should only call this method after a + * supported state callback on {@link Callback#onAvailabilityChanged(int)} to avoid this + * exception. + * @throws IllegalStateException Thrown when a caller has a target SDK below API level 33 if the + * detector is in an invalid or error state. This may happen if another detector has + * been instantiated or the {@link VoiceInteractionService} hosting this detector has + * been shut down. */ // TODO: Remove this RequiresPermission since it isn't actually enforced. Also fix the javadoc // about permissions enforcement (when it throws vs when it just returns false) for other // methods in this class. @RequiresPermission(allOf = {RECORD_AUDIO, CAPTURE_AUDIO_HOTWORD}) @Override - public boolean stopRecognition() { + public boolean stopRecognition() throws IllegalDetectorStateException { if (DBG) Slog.d(TAG, "stopRecognition()"); synchronized (mLock) { if (mAvailability == STATE_INVALID || mAvailability == STATE_ERROR) { + if (CompatChanges.isChangeEnabled(HOTWORD_DETECTOR_THROW_CHECKED_EXCEPTION)) { + throw new IllegalDetectorStateException( + "stopRecognition called on an invalid detector or error state"); + } throw new IllegalStateException( "stopRecognition called on an invalid detector or error state"); } // Check if we can start/stop a recognition. if (mAvailability != STATE_KEYPHRASE_ENROLLED) { + if (CompatChanges.isChangeEnabled(HOTWORD_DETECTOR_THROW_CHECKED_EXCEPTION)) { + throw new IllegalDetectorStateException( + "Recognition for the given keyphrase is not supported"); + } throw new UnsupportedOperationException( "Recognition for the given keyphrase is not supported"); } @@ -1039,18 +1190,28 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { * - {@link SoundTrigger#STATUS_BAD_VALUE} invalid input parameter * - {@link SoundTrigger#STATUS_INVALID_OPERATION} if the call is out of sequence or * if API is not supported by HAL - * @throws IllegalStateException if the detector is in an invalid or error state. - * This may happen if another detector has been instantiated or the - * {@link VoiceInteractionService} hosting this detector has been shut down. + * @throws IllegalDetectorStateException Thrown when a caller has a target SDK of API level 33 + * if the detector is in an invalid or error state. This may happen if another detector + * has been instantiated or the {@link VoiceInteractionService} hosting this detector + * has been shut down. + * @throws IllegalStateException Thrown when a caller has a target SDK below API level 33 if the + * detector is in an invalid or error state. This may happen if another detector has + * been instantiated or the {@link VoiceInteractionService} hosting this detector has + * been shut down. */ @RequiresPermission(allOf = {RECORD_AUDIO, CAPTURE_AUDIO_HOTWORD}) - public int setParameter(@ModelParams int modelParam, int value) { + public int setParameter(@ModelParams int modelParam, int value) + throws IllegalDetectorStateException { if (DBG) { Slog.d(TAG, "setParameter(" + modelParam + ", " + value + ")"); } synchronized (mLock) { if (mAvailability == STATE_INVALID || mAvailability == STATE_ERROR) { + if (CompatChanges.isChangeEnabled(HOTWORD_DETECTOR_THROW_CHECKED_EXCEPTION)) { + throw new IllegalDetectorStateException( + "setParameter called on an invalid detector or error state"); + } throw new IllegalStateException( "setParameter called on an invalid detector or error state"); } @@ -1071,18 +1232,27 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { * * @param modelParam {@link ModelParams} * @return value of parameter - * @throws IllegalStateException if the detector is in an invalid or error state. - * This may happen if another detector has been instantiated or the - * {@link VoiceInteractionService} hosting this detector has been shut down. + * @throws IllegalDetectorStateException Thrown when a caller has a target SDK of API level 33 + * if the detector is in an invalid or error state. This may happen if another detector + * has been instantiated or the {@link VoiceInteractionService} hosting this detector + * has been shut down. + * @throws IllegalStateException Thrown when a caller has a target SDK below API level 33 if + * the detector is in an invalid or error state. This may happen if another detector has + * been instantiated or the {@link VoiceInteractionService} hosting this detector has + * been shut down. */ @RequiresPermission(allOf = {RECORD_AUDIO, CAPTURE_AUDIO_HOTWORD}) - public int getParameter(@ModelParams int modelParam) { + public int getParameter(@ModelParams int modelParam) throws IllegalDetectorStateException { if (DBG) { Slog.d(TAG, "getParameter(" + modelParam + ")"); } synchronized (mLock) { if (mAvailability == STATE_INVALID || mAvailability == STATE_ERROR) { + if (CompatChanges.isChangeEnabled(HOTWORD_DETECTOR_THROW_CHECKED_EXCEPTION)) { + throw new IllegalDetectorStateException( + "getParameter called on an invalid detector or error state"); + } throw new IllegalStateException( "getParameter called on an invalid detector or error state"); } @@ -1100,19 +1270,29 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { * * @param modelParam {@link ModelParams} * @return supported range of parameter, null if not supported - * @throws IllegalStateException if the detector is in an invalid or error state. - * This may happen if another detector has been instantiated or the - * {@link VoiceInteractionService} hosting this detector has been shut down. + * @throws IllegalDetectorStateException Thrown when a caller has a target SDK of API level 33 + * if the detector is in an invalid or error state. This may happen if another detector + * has been instantiated or the {@link VoiceInteractionService} hosting this detector + * has been shut down. + * @throws IllegalStateException Thrown when a caller has a target SDK below API level 33 if + * the detector is in an invalid or error state. This may happen if another detector has + * been instantiated or the {@link VoiceInteractionService} hosting this detector has + * been shut down. */ @RequiresPermission(allOf = {RECORD_AUDIO, CAPTURE_AUDIO_HOTWORD}) @Nullable - public ModelParamRange queryParameter(@ModelParams int modelParam) { + public ModelParamRange queryParameter(@ModelParams int modelParam) + throws IllegalDetectorStateException { if (DBG) { Slog.d(TAG, "queryParameter(" + modelParam + ")"); } synchronized (mLock) { if (mAvailability == STATE_INVALID || mAvailability == STATE_ERROR) { + if (CompatChanges.isChangeEnabled(HOTWORD_DETECTOR_THROW_CHECKED_EXCEPTION)) { + throw new IllegalDetectorStateException( + "queryParameter called on an invalid detector or error state"); + } throw new IllegalStateException( "queryParameter called on an invalid detector or error state"); } @@ -1129,15 +1309,25 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { * otherwise {@link #createReEnrollIntent()} should be preferred. * * @return An {@link Intent} to start enrollment for the given keyphrase. - * @throws UnsupportedOperationException if managing they keyphrase isn't supported. - * Callers should only call this method after a supported state callback on - * {@link Callback#onAvailabilityChanged(int)} to avoid this exception. - * @throws IllegalStateException if the detector is in an invalid state. - * This may happen if another detector has been instantiated or the - * {@link VoiceInteractionService} hosting this detector has been shut down. + * @throws IllegalDetectorStateException Thrown when a caller has a target SDK of API level 33 + * or above. + * - Thrown if managing they keyphrase isn't supported. Callers should only call this + * method after a supported state callback on + * {@link Callback#onAvailabilityChanged(int)} to avoid this exception. + * - Thrown if the detector is in an invalid state. This may happen if another detector + * has been instantiated or the {@link VoiceInteractionService} hosting this detector + * has been shut down. + * @throws UnsupportedOperationException Thrown when a caller has a target SDK below API level + * 33 if managing they keyphrase isn't supported. Callers should only call this method + * after a supported state callback on {@link Callback#onAvailabilityChanged(int)} to + * avoid this exception. + * @throws IllegalStateException Thrown when a caller has a target SDK below API level 33 if the + * detector is in an invalid state. This may happen if another detector has been + * instantiated or the {@link VoiceInteractionService} hosting this detector has been + * shut down. */ @Nullable - public Intent createEnrollIntent() { + public Intent createEnrollIntent() throws IllegalDetectorStateException { if (DBG) Slog.d(TAG, "createEnrollIntent"); synchronized (mLock) { return getManageIntentLocked(KeyphraseEnrollmentInfo.MANAGE_ACTION_ENROLL); @@ -1151,15 +1341,25 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { * i.e. {@link #STATE_KEYPHRASE_ENROLLED}, otherwise invoking this may result in an error. * * @return An {@link Intent} to start un-enrollment for the given keyphrase. - * @throws UnsupportedOperationException if managing they keyphrase isn't supported. - * Callers should only call this method after a supported state callback on - * {@link Callback#onAvailabilityChanged(int)} to avoid this exception. - * @throws IllegalStateException if the detector is in an invalid state. - * This may happen if another detector has been instantiated or the - * {@link VoiceInteractionService} hosting this detector has been shut down. + * @throws IllegalDetectorStateException Thrown when a caller has a target SDK of API level 33 + * or above. + * - Thrown if managing they keyphrase isn't supported. Callers should only call this + * method after a supported state callback on + * {@link Callback#onAvailabilityChanged(int)} to avoid this exception. + * - Thrown if the detector is in an invalid state. This may happen if another detector + * has been instantiated or the {@link VoiceInteractionService} hosting this detector + * has been shut down. + * @throws UnsupportedOperationException Thrown when a caller has a target SDK below API level + * 33 if managing they keyphrase isn't supported. Callers should only call this method + * after a supported state callback on {@link Callback#onAvailabilityChanged(int)} to + * avoid this exception. + * @throws IllegalStateException Thrown when a caller has a target SDK below API level 33 if the + * detector is in an invalid state. This may happen if another detector has been + * instantiated or the {@link VoiceInteractionService} hosting this detector has been + * shut down. */ @Nullable - public Intent createUnEnrollIntent() { + public Intent createUnEnrollIntent() throws IllegalDetectorStateException { if (DBG) Slog.d(TAG, "createUnEnrollIntent"); synchronized (mLock) { return getManageIntentLocked(KeyphraseEnrollmentInfo.MANAGE_ACTION_UN_ENROLL); @@ -1173,30 +1373,50 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { * i.e. {@link #STATE_KEYPHRASE_ENROLLED}, otherwise invoking this may result in an error. * * @return An {@link Intent} to start re-enrollment for the given keyphrase. - * @throws UnsupportedOperationException if managing they keyphrase isn't supported. - * Callers should only call this method after a supported state callback on - * {@link Callback#onAvailabilityChanged(int)} to avoid this exception. - * @throws IllegalStateException if the detector is in an invalid or error state. - * This may happen if another detector has been instantiated or the - * {@link VoiceInteractionService} hosting this detector has been shut down. + * @throws IllegalDetectorStateException Thrown when a caller has a target SDK of API level 33 + * or above. + * - Thrown if managing they keyphrase isn't supported. Callers should only call this + * method after a supported state callback on + * {@link Callback#onAvailabilityChanged(int)} to avoid this exception. + * - Thrown if the detector is in an invalid state. This may happen if another detector + * has been instantiated or the {@link VoiceInteractionService} hosting this detector + * has been shut down. + * @throws UnsupportedOperationException Thrown when a caller has a target SDK below API level + * 33 if managing they keyphrase isn't supported. Callers should only call this method + * after a supported state callback on {@link Callback#onAvailabilityChanged(int)} to + * avoid this exception. + * @throws IllegalStateException Thrown when a caller has a target SDK below API level 33 if the + * detector is in an invalid state. This may happen if another detector has been + * instantiated or the {@link VoiceInteractionService} hosting this detector has been + * shut down. */ @Nullable - public Intent createReEnrollIntent() { + public Intent createReEnrollIntent() throws IllegalDetectorStateException { if (DBG) Slog.d(TAG, "createReEnrollIntent"); synchronized (mLock) { return getManageIntentLocked(KeyphraseEnrollmentInfo.MANAGE_ACTION_RE_ENROLL); } } - private Intent getManageIntentLocked(@KeyphraseEnrollmentInfo.ManageActions int action) { + @GuardedBy("mLock") + private Intent getManageIntentLocked(@KeyphraseEnrollmentInfo.ManageActions int action) + throws IllegalDetectorStateException { if (mAvailability == STATE_INVALID || mAvailability == STATE_ERROR) { + if (CompatChanges.isChangeEnabled(HOTWORD_DETECTOR_THROW_CHECKED_EXCEPTION)) { + throw new IllegalDetectorStateException( + "getManageIntent called on an invalid detector or error state"); + } throw new IllegalStateException( - "getManageIntent called on an invalid detector or error state"); + "getManageIntent called on an invalid detector or error state"); } // This method only makes sense if we can actually support a recognition. if (mAvailability != STATE_KEYPHRASE_ENROLLED && mAvailability != STATE_KEYPHRASE_UNENROLLED) { + if (CompatChanges.isChangeEnabled(HOTWORD_DETECTOR_THROW_CHECKED_EXCEPTION)) { + throw new IllegalDetectorStateException( + "Managing the given keyphrase is not supported"); + } throw new UnsupportedOperationException( "Managing the given keyphrase is not supported"); } @@ -1212,24 +1432,29 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { public void destroy() { synchronized (mLock) { if (mAvailability == STATE_KEYPHRASE_ENROLLED) { - stopRecognition(); + try { + stopRecognition(); + } catch (Exception e) { + Log.i(TAG, "failed to stopRecognition in destroy", e); + } } mAvailability = STATE_INVALID; + mIsAvailabilityOverriddenByTestApi = false; notifyStateChangedLocked(); - - if (mSupportHotwordDetectionService) { - try { - mModelManagementService.shutdownHotwordDetectionService(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } } super.destroy(); } /** + * @hide + */ + @Override + public boolean isUsingHotwordDetectionService() { + return mSupportHotwordDetectionService; + } + + /** * Reloads the sound models from the service. * * @hide @@ -1244,6 +1469,15 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { return; } + // Because this method reflects an update from the system service models, we should not + // update the client of an availability change when the availability has been overridden + // via a test API. + if (mIsAvailabilityOverriddenByTestApi) { + Slog.w(TAG, "Suppressing system availability update. " + + "Availability is overridden by test API."); + return; + } + // Stop the recognition before proceeding. // This is done because we want to stop the recognition on an older model if it changed // or was deleted. @@ -1263,11 +1497,37 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { } // Execute a refresh availability task - which should then notify of a change. - new RefreshAvailabiltyTask().execute(); + new RefreshAvailabilityTask().execute(); } } - private int startRecognitionLocked(int recognitionFlags) { + @GuardedBy("mLock") + private int startRecognitionLocked(int recognitionFlags, + @Nullable byte[] data) throws IllegalDetectorStateException { + if (DBG) { + Slog.d(TAG, "startRecognition(" + + recognitionFlags + + ", " + Arrays.toString(data) + ")"); + } + if (mAvailability == STATE_INVALID || mAvailability == STATE_ERROR) { + if (CompatChanges.isChangeEnabled(HOTWORD_DETECTOR_THROW_CHECKED_EXCEPTION)) { + throw new IllegalDetectorStateException( + "startRecognition called on an invalid detector or error state"); + } + throw new IllegalStateException( + "startRecognition called on an invalid detector or error state"); + } + + // Check if we can start/stop a recognition. + if (mAvailability != STATE_KEYPHRASE_ENROLLED) { + if (CompatChanges.isChangeEnabled(HOTWORD_DETECTOR_THROW_CHECKED_EXCEPTION)) { + throw new IllegalDetectorStateException( + "Recognition for the given keyphrase is not supported"); + } + throw new UnsupportedOperationException( + "Recognition for the given keyphrase is not supported"); + } + KeyphraseRecognitionExtra[] recognitionExtra = new KeyphraseRecognitionExtra[1]; // TODO: Do we need to do something about the confidence level here? recognitionExtra[0] = new KeyphraseRecognitionExtra(mKeyphraseMetadata.getId(), @@ -1291,7 +1551,7 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { code = mSoundTriggerSession.startRecognition( mKeyphraseMetadata.getId(), mLocale.toLanguageTag(), mInternalCallback, new RecognitionConfig(captureTriggerAudio, allowMultipleTriggers, - recognitionExtra, null /* additional data */, audioCapabilities), + recognitionExtra, data, audioCapabilities), runInBatterySaver); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -1303,6 +1563,7 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { return code; } + @GuardedBy("mLock") private int stopRecognitionLocked() { int code; try { @@ -1318,6 +1579,7 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { return code; } + @GuardedBy("mLock") private int setParameterLocked(@ModelParams int modelParam, int value) { try { int code = mSoundTriggerSession.setParameter(mKeyphraseMetadata.getId(), modelParam, @@ -1333,6 +1595,7 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { } } + @GuardedBy("mLock") private int getParameterLocked(@ModelParams int modelParam) { try { return mSoundTriggerSession.getParameter(mKeyphraseMetadata.getId(), modelParam); @@ -1341,6 +1604,7 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { } } + @GuardedBy("mLock") @Nullable private ModelParamRange queryParameterLocked(@ModelParams int modelParam) { try { @@ -1357,15 +1621,19 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { } } + @GuardedBy("mLock") private void updateAndNotifyStateChangedLocked(int availability) { if (DBG) { Slog.d(TAG, "Hotword availability changed from " + mAvailability + " -> " + availability); } - mAvailability = availability; + if (!mIsAvailabilityOverriddenByTestApi) { + mAvailability = availability; + } notifyStateChangedLocked(); } + @GuardedBy("mLock") private void notifyStateChangedLocked() { Message message = Message.obtain(mHandler, MSG_AVAILABILITY_CHANGED); message.arg1 = mAvailability; @@ -1487,7 +1755,7 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { } } - class RefreshAvailabiltyTask extends AsyncTask<Void, Void, Void> { + class RefreshAvailabilityTask extends AsyncTask<Void, Void, Void> { @Override public Void doInBackground(Void... params) { @@ -1555,7 +1823,26 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { } } + @Override + public boolean equals(Object obj) { + if (CompatChanges.isChangeEnabled(MULTIPLE_ACTIVE_HOTWORD_DETECTORS)) { + if (!(obj instanceof AlwaysOnHotwordDetector)) { + return false; + } + AlwaysOnHotwordDetector other = (AlwaysOnHotwordDetector) obj; + return TextUtils.equals(mText, other.mText) && mLocale.equals(other.mLocale); + } + + return super.equals(obj); + } + + @Override + public int hashCode() { + return Objects.hash(mText, mLocale); + } + /** @hide */ + @Override public void dump(String prefix, PrintWriter pw) { synchronized (mLock) { pw.print(prefix); pw.print("Text="); pw.println(mText); diff --git a/core/java/android/service/voice/HotwordDetectionService.java b/core/java/android/service/voice/HotwordDetectionService.java index d755d3877275..c46041c5e330 100644 --- a/core/java/android/service/voice/HotwordDetectionService.java +++ b/core/java/android/service/voice/HotwordDetectionService.java @@ -243,13 +243,26 @@ public abstract class HotwordDetectionService extends Service { /** * Called when the device hardware (such as a DSP) detected the hotword, to request second stage * validation before handing over the audio to the {@link AlwaysOnHotwordDetector}. - * <p> - * After {@code callback} is invoked or {@code timeoutMillis} has passed, and invokes the + * + * <p>After {@code callback} is invoked or {@code timeoutMillis} has passed, and invokes the * appropriate {@link AlwaysOnHotwordDetector.Callback callback}. * + * <p>When responding to a detection event, the + * {@link HotwordDetectedResult#getHotwordPhraseId()} must match a keyphrase ID listed + * in the eventPayload's + * {@link AlwaysOnHotwordDetector.EventPayload#getKeyphraseRecognitionExtras()} list. This is + * forcing the intention of the {@link HotwordDetectionService} to validate an event from the + * voice engine and not augment its result. + * * @param eventPayload Payload data for the hardware detection event. This may contain the - * trigger audio, if requested when calling - * {@link AlwaysOnHotwordDetector#startRecognition(int)}. + * trigger audio, if requested when calling + * {@link AlwaysOnHotwordDetector#startRecognition(int)}. + * Each {@link AlwaysOnHotwordDetector} will be associated with at minimum a unique + * keyphrase ID indicated by + * {@link AlwaysOnHotwordDetector.EventPayload#getKeyphraseRecognitionExtras()}[0]. + * Any extra + * {@link android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionExtra}'s + * in the eventPayload represent additional phrases detected by the voice engine. * @param timeoutMillis Timeout in milliseconds for the operation to invoke the callback. If * the application fails to abide by the timeout, system will close the * microphone and cancel the operation. diff --git a/core/java/android/service/voice/HotwordDetector.java b/core/java/android/service/voice/HotwordDetector.java index 96fd8bbda016..1a0dc8945b63 100644 --- a/core/java/android/service/voice/HotwordDetector.java +++ b/core/java/android/service/voice/HotwordDetector.java @@ -23,10 +23,16 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; +import android.compat.annotation.ChangeId; +import android.compat.annotation.EnabledSince; import android.media.AudioFormat; +import android.os.Build; import android.os.ParcelFileDescriptor; import android.os.PersistableBundle; import android.os.SharedMemory; +import android.util.AndroidException; + +import java.io.PrintWriter; /** * Basic functionality for hotword detectors. @@ -37,6 +43,23 @@ import android.os.SharedMemory; public interface HotwordDetector { /** + * Prior to API level 33, API calls of {@link android.service.voice.HotwordDetector} could + * return both {@link java.lang.IllegalStateException} or + * {@link java.lang.UnsupportedOperationException} depending on the detector's underlying state. + * This lead to confusing behavior as the underlying state of the detector can be modified + * without the knowledge of the caller via system service layer updates. + * + * This change ID, when enabled, changes the API calls to only throw checked exception + * {@link android.service.voice.HotwordDetector.IllegalDetectorStateException} when checking + * against state information modified by both the caller and the system services. + * + * @hide + */ + @ChangeId + @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU) + long HOTWORD_DETECTOR_THROW_CHECKED_EXCEPTION = 226355112L; + + /** * Indicates that it is a non-trusted hotword detector. * * @hide @@ -74,16 +97,26 @@ public interface HotwordDetector { * Calling this again while recognition is active does nothing. * * @return true if the request to start recognition succeeded + * @throws IllegalDetectorStateException Thrown when a caller has a target SDK of API level 33 + * or above and attempts to start a recognition when the detector is not able based on + * the state. This can be thrown even if the state has been checked before calling this + * method because the caller receives updates via an asynchronous callback, and the + * state of the detector can change concurrently to the caller calling this method. */ @RequiresPermission(allOf = {RECORD_AUDIO, CAPTURE_AUDIO_HOTWORD}) - boolean startRecognition(); + boolean startRecognition() throws IllegalDetectorStateException; /** * Stops hotword recognition. * * @return true if the request to stop recognition succeeded + * @throws IllegalDetectorStateException Thrown when a caller has a target SDK of API level 33 + * or above and attempts to stop a recognition when the detector is not able based on + * the state. This can be thrown even if the state has been checked before calling this + * method because the caller receives updates via an asynchronous callback, and the + * state of the detector can change concurrently to the caller calling this method. */ - boolean stopRecognition(); + boolean stopRecognition() throws IllegalDetectorStateException; /** * Starts hotword recognition on audio coming from an external connected microphone. @@ -97,26 +130,37 @@ public interface HotwordDetector { * PersistableBundle does not allow any remotable objects or other contents that can be * used to communicate with other processes. * @return true if the request to start recognition succeeded + * @throws IllegalDetectorStateException Thrown when a caller has a target SDK of API level 33 + * or above and attempts to start a recognition when the detector is not able based on + * the state. This can be thrown even if the state has been checked before calling this + * method because the caller receives updates via an asynchronous callback, and the + * state of the detector can change concurrently to the caller calling this method. */ boolean startRecognition( @NonNull ParcelFileDescriptor audioStream, @NonNull AudioFormat audioFormat, - @Nullable PersistableBundle options); + @Nullable PersistableBundle options) throws IllegalDetectorStateException; /** * Set configuration and pass read-only data to hotword detection service. * * @param options Application configuration data to provide to the - * {@link HotwordDetectionService}. PersistableBundle does not allow any remotable objects or - * other contents that can be used to communicate with other processes. + * {@link HotwordDetectionService}. PersistableBundle does not allow any remotable + * objects or other contents that can be used to communicate with other processes. * @param sharedMemory The unrestricted data blob to provide to the - * {@link HotwordDetectionService}. Use this to provide the hotword models data or other - * such data to the trusted process. - * + * {@link HotwordDetectionService}. Use this to provide the hotword models data or other + * such data to the trusted process. + * @throws IllegalDetectorStateException Thrown when a caller has a target SDK of API level 33 + * or above and the detector is not able to perform the operation based on the + * underlying state. This can be thrown even if the state has been checked before + * calling this method because the caller receives updates via an asynchronous callback, + * and the state of the detector can change concurrently to the caller calling this + * method. * @throws IllegalStateException if this HotwordDetector wasn't specified to use a - * {@link HotwordDetectionService} when it was created. + * {@link HotwordDetectionService} when it was created. */ - void updateState(@Nullable PersistableBundle options, @Nullable SharedMemory sharedMemory); + void updateState(@Nullable PersistableBundle options, @Nullable SharedMemory sharedMemory) + throws IllegalDetectorStateException; /** * Invalidates this hotword detector so that any future calls to this result @@ -132,6 +176,13 @@ public interface HotwordDetector { /** * @hide */ + default boolean isUsingHotwordDetectionService() { + throw new UnsupportedOperationException("Not implemented. Must override in a subclass."); + } + + /** + * @hide + */ static String detectorTypeToString(int detectorType) { switch (detectorType) { case DETECTOR_TYPE_NORMAL: @@ -145,6 +196,11 @@ public interface HotwordDetector { } } + /** @hide */ + default void dump(String prefix, PrintWriter pw) { + throw new UnsupportedOperationException("Not implemented. Must override in a subclass."); + } + /** * The callback to notify of detection events. */ @@ -205,4 +261,14 @@ public interface HotwordDetector { */ void onHotwordDetectionServiceRestarted(); } + + /** + * {@link HotwordDetector} specific exception thrown when the underlying state of the detector + * is invalid for the given action. + */ + class IllegalDetectorStateException extends AndroidException { + IllegalDetectorStateException(String message) { + super(message); + } + } } diff --git a/core/java/android/service/voice/SoftwareHotwordDetector.java b/core/java/android/service/voice/SoftwareHotwordDetector.java index 2d662eaf0a4f..36ea91e4edb5 100644 --- a/core/java/android/service/voice/SoftwareHotwordDetector.java +++ b/core/java/android/service/voice/SoftwareHotwordDetector.java @@ -30,6 +30,7 @@ import android.os.ParcelFileDescriptor; import android.os.PersistableBundle; import android.os.RemoteException; import android.os.SharedMemory; +import android.util.Log; import android.util.Slog; import com.android.internal.app.IHotwordRecognitionStatusCallback; @@ -57,8 +58,6 @@ class SoftwareHotwordDetector extends AbstractHotwordDetector { SoftwareHotwordDetector( IVoiceInteractionManagerService managerService, AudioFormat audioFormat, - PersistableBundle options, - SharedMemory sharedMemory, HotwordDetector.Callback callback) { super(managerService, callback, DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE); @@ -66,6 +65,12 @@ class SoftwareHotwordDetector extends AbstractHotwordDetector { mAudioFormat = audioFormat; mCallback = callback; mHandler = new Handler(Looper.getMainLooper()); + } + + @Override + void initialize(@Nullable PersistableBundle options, @Nullable SharedMemory sharedMemory) { + // TODO: transition to use an API that is not updateState to provide + // onHotwordDetectionServiceInitialized status to external callback updateStateLocked(options, sharedMemory, new InitializationStateListener(mHandler, mCallback), DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE); @@ -73,7 +78,7 @@ class SoftwareHotwordDetector extends AbstractHotwordDetector { @RequiresPermission(RECORD_AUDIO) @Override - public boolean startRecognition() { + public boolean startRecognition() throws IllegalDetectorStateException { if (DEBUG) { Slog.i(TAG, "#startRecognition"); } @@ -96,7 +101,7 @@ class SoftwareHotwordDetector extends AbstractHotwordDetector { /** TODO: stopRecognition */ @RequiresPermission(RECORD_AUDIO) @Override - public boolean stopRecognition() { + public boolean stopRecognition() throws IllegalDetectorStateException { if (DEBUG) { Slog.i(TAG, "#stopRecognition"); } @@ -113,17 +118,23 @@ class SoftwareHotwordDetector extends AbstractHotwordDetector { @Override public void destroy() { - stopRecognition(); - maybeCloseExistingSession(); - try { - mManagerService.shutdownHotwordDetectionService(); - } catch (RemoteException ex) { - ex.rethrowFromSystemServer(); + stopRecognition(); + } catch (Exception e) { + Log.i(TAG, "failed to stopRecognition in destroy", e); } + maybeCloseExistingSession(); super.destroy(); } + /** + * @hide + */ + @Override + public boolean isUsingHotwordDetectionService() { + return true; + } + private void maybeCloseExistingSession() { // TODO: needs to be synchronized. // TODO: implement this @@ -231,6 +242,7 @@ class SoftwareHotwordDetector extends AbstractHotwordDetector { } /** @hide */ + @Override public void dump(String prefix, PrintWriter pw) { // TODO: implement this } diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java index bf0cfbe49f31..1170237a346e 100644 --- a/core/java/android/service/voice/VoiceInteractionService.java +++ b/core/java/android/service/voice/VoiceInteractionService.java @@ -24,12 +24,16 @@ import android.annotation.SdkConstant; import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.app.Service; +import android.app.compat.CompatChanges; +import android.compat.annotation.ChangeId; +import android.compat.annotation.EnabledSince; import android.compat.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.hardware.soundtrigger.KeyphraseEnrollmentInfo; import android.media.voice.KeyphraseModelManager; +import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -89,6 +93,37 @@ public class VoiceInteractionService extends Service { */ public static final String SERVICE_META_DATA = "android.voice_interaction"; + /** + * For apps targeting Build.VERSION_CODES.TRAMISU and above, implementors of this + * service can create multiple AlwaysOnHotwordDetector instances in parallel. They will + * also e ale to create a single SoftwareHotwordDetector in parallel with any other + * active AlwaysOnHotwordDetector instances. + * + * <p>Requirements when this change is enabled: + * <ul> + * <li> + * Any number of AlwaysOnHotwordDetector instances can be created in parallel + * as long as they are unique to any other active AlwaysOnHotwordDetector. + * </li> + * <li> + * Only a single instance of SoftwareHotwordDetector can be active at a given + * time. It can be active at the same time as any number of + * AlwaysOnHotwordDetector instances. + * </li> + * <li> + * To release that reference and any resources associated with that reference, + * HotwordDetector#destroy() must be called. An attempt to create an + * HotwordDetector equal to an active HotwordDetector will be rejected + * until HotwordDetector#destroy() is called on the active instance. + * </li> + * </ul> + * + * @hide + */ + @ChangeId + @EnabledSince(targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT) + static final long MULTIPLE_ACTIVE_HOTWORD_DETECTORS = 193232191L; + IVoiceInteractionService mInterface = new IVoiceInteractionService.Stub() { @Override public void ready() { @@ -133,8 +168,7 @@ public class VoiceInteractionService extends Service { private KeyphraseEnrollmentInfo mKeyphraseEnrollmentInfo; - private AlwaysOnHotwordDetector mHotwordDetector; - private SoftwareHotwordDetector mSoftwareHotwordDetector; + private final Set<HotwordDetector> mActiveHotwordDetectors = new ArraySet<>(); /** * Called when a user has activated an affordance to launch voice assist from the Keyguard. @@ -284,10 +318,12 @@ public class VoiceInteractionService extends Service { private void onSoundModelsChangedInternal() { synchronized (this) { - if (mHotwordDetector != null) { - // TODO: Stop recognition if a sound model that was being recognized gets deleted. - mHotwordDetector.onSoundModelsChanged(); - } + // TODO: Stop recognition if a sound model that was being recognized gets deleted. + mActiveHotwordDetectors.forEach(detector -> { + if (detector instanceof AlwaysOnHotwordDetector) { + ((AlwaysOnHotwordDetector) detector).onSoundModelsChanged(); + } + }); } } @@ -379,16 +415,31 @@ public class VoiceInteractionService extends Service { throw new IllegalStateException("Not available until onReady() is called"); } synchronized (mLock) { - // Allow only one concurrent recognition via the APIs. - safelyShutdownAllHotwordDetectors(); - mHotwordDetector = new AlwaysOnHotwordDetector(keyphrase, locale, callback, - mKeyphraseEnrollmentInfo, mSystemService, + if (!CompatChanges.isChangeEnabled(MULTIPLE_ACTIVE_HOTWORD_DETECTORS)) { + // Allow only one concurrent recognition via the APIs. + safelyShutdownAllHotwordDetectors(); + } + + AlwaysOnHotwordDetector dspDetector = new AlwaysOnHotwordDetector(keyphrase, locale, + callback, mKeyphraseEnrollmentInfo, mSystemService, getApplicationContext().getApplicationInfo().targetSdkVersion, - supportHotwordDetectionService, options, sharedMemory); - mHotwordDetector.registerOnDestroyListener((detector) -> onDspHotwordDetectorDestroyed( - (AlwaysOnHotwordDetector) detector)); + supportHotwordDetectionService); + if (!mActiveHotwordDetectors.add(dspDetector)) { + throw new IllegalArgumentException( + "the keyphrase=" + keyphrase + " and locale=" + locale + + " are already used by another always-on detector"); + } + + try { + dspDetector.registerOnDestroyListener(this::onHotwordDetectorDestroyed); + dspDetector.initialize(options, sharedMemory); + } catch (Exception e) { + mActiveHotwordDetectors.remove(dspDetector); + dspDetector.destroy(); + throw e; + } + return dspDetector; } - return mHotwordDetector; } /** @@ -434,16 +485,34 @@ public class VoiceInteractionService extends Service { throw new IllegalStateException("Not available until onReady() is called"); } synchronized (mLock) { - // Allow only one concurrent recognition via the APIs. - safelyShutdownAllHotwordDetectors(); - mSoftwareHotwordDetector = + if (!CompatChanges.isChangeEnabled(MULTIPLE_ACTIVE_HOTWORD_DETECTORS)) { + // Allow only one concurrent recognition via the APIs. + safelyShutdownAllHotwordDetectors(); + } else { + for (HotwordDetector detector : mActiveHotwordDetectors) { + if (detector instanceof SoftwareHotwordDetector) { + throw new IllegalArgumentException( + "There is already an active SoftwareHotwordDetector. " + + "It must be destroyed to create a new one."); + } + } + } + + SoftwareHotwordDetector softwareHotwordDetector = new SoftwareHotwordDetector( - mSystemService, null, options, sharedMemory, callback); - mSoftwareHotwordDetector.registerOnDestroyListener( - (detector) -> onMicrophoneHotwordDetectorDestroyed( - (SoftwareHotwordDetector) detector)); + mSystemService, null, callback); + + try { + softwareHotwordDetector.registerOnDestroyListener( + this::onHotwordDetectorDestroyed); + softwareHotwordDetector.initialize(options, sharedMemory); + } catch (Exception e) { + mActiveHotwordDetectors.remove(softwareHotwordDetector); + softwareHotwordDetector.destroy(); + throw e; + } + return softwareHotwordDetector; } - return mSoftwareHotwordDetector; } /** @@ -489,33 +558,34 @@ public class VoiceInteractionService extends Service { private void safelyShutdownAllHotwordDetectors() { synchronized (mLock) { - if (mHotwordDetector != null) { + mActiveHotwordDetectors.forEach(detector -> { try { - mHotwordDetector.destroy(); + detector.destroy(); } catch (Exception ex) { - Log.i(TAG, "exception destroying AlwaysOnHotwordDetector", ex); + Log.i(TAG, "exception destroying HotwordDetector", ex); } - } - - if (mSoftwareHotwordDetector != null) { - try { - mSoftwareHotwordDetector.destroy(); - } catch (Exception ex) { - Log.i(TAG, "exception destroying SoftwareHotwordDetector", ex); - } - } + }); } } - private void onDspHotwordDetectorDestroyed(@NonNull AlwaysOnHotwordDetector detector) { + private void onHotwordDetectorDestroyed(@NonNull HotwordDetector detector) { synchronized (mLock) { - mHotwordDetector = null; + mActiveHotwordDetectors.remove(detector); + shutdownHotwordDetectionServiceIfRequiredLocked(); } } - private void onMicrophoneHotwordDetectorDestroyed(@NonNull SoftwareHotwordDetector detector) { - synchronized (mLock) { - mSoftwareHotwordDetector = null; + private void shutdownHotwordDetectionServiceIfRequiredLocked() { + for (HotwordDetector detector : mActiveHotwordDetectors) { + if (detector.isUsingHotwordDetectionService()) { + return; + } + } + + try { + mSystemService.shutdownHotwordDetectionService(); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); } } @@ -540,18 +610,14 @@ public class VoiceInteractionService extends Service { protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("VOICE INTERACTION"); synchronized (mLock) { - pw.println(" AlwaysOnHotwordDetector"); - if (mHotwordDetector == null) { - pw.println(" NULL"); - } else { - mHotwordDetector.dump(" ", pw); - } - - pw.println(" MicrophoneHotwordDetector"); - if (mSoftwareHotwordDetector == null) { + pw.println(" HotwordDetector(s)"); + if (mActiveHotwordDetectors.size() == 0) { pw.println(" NULL"); } else { - mSoftwareHotwordDetector.dump(" ", pw); + mActiveHotwordDetectors.forEach(detector -> { + detector.dump(" ", pw); + pw.println(); + }); } } } diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java index 2f85d2b63840..520ceb2582db 100644 --- a/core/java/android/text/StaticLayout.java +++ b/core/java/android/text/StaticLayout.java @@ -25,6 +25,7 @@ import android.graphics.Paint; import android.graphics.text.LineBreakConfig; import android.graphics.text.LineBreaker; import android.os.Build; +import android.os.SystemProperties; import android.text.style.LeadingMarginSpan; import android.text.style.LeadingMarginSpan.LeadingMarginSpan2; import android.text.style.LineHeightSpan; @@ -32,6 +33,7 @@ import android.text.style.TabStopSpan; import android.util.Log; import android.util.Pools.SynchronizedPool; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.internal.util.GrowingArrayUtils; @@ -73,6 +75,13 @@ public class StaticLayout extends Layout { * default values. */ public final static class Builder { + // The content length threshold to enable LINE_BREAK_WORD_STYLE_PHRASE. + private static final int DEFAULT_LINECOUNT_THRESHOLD_FOR_PHRASE = 3; + + // The property of content length threshold to enable LINE_BREAK_WORD_STYLE_PHRASE. + private static final String PROPERTY_LINECOUNT_THRESHOLD_FOR_PHRASE = + "android.phrase.linecount.threshold"; + private Builder() {} /** @@ -431,11 +440,55 @@ public class StaticLayout extends Layout { */ @NonNull public StaticLayout build() { + reviseLineBreakConfig(); StaticLayout result = new StaticLayout(this); Builder.recycle(this); return result; } + private void reviseLineBreakConfig() { + boolean autoPhraseBreaking = mLineBreakConfig.getAutoPhraseBreaking(); + int wordStyle = mLineBreakConfig.getLineBreakWordStyle(); + if (autoPhraseBreaking) { + if (wordStyle != LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE) { + if (shouldEnablePhraseBreaking()) { + mLineBreakConfig = LineBreakConfig.getLineBreakConfig( + mLineBreakConfig.getLineBreakStyle(), + LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE, + mLineBreakConfig.getAutoPhraseBreaking()); + } + } + } + } + + private boolean shouldEnablePhraseBreaking() { + if (TextUtils.isEmpty(mText) || mWidth <= 0) { + return false; + } + int lineLimit = SystemProperties.getInt( + PROPERTY_LINECOUNT_THRESHOLD_FOR_PHRASE, + DEFAULT_LINECOUNT_THRESHOLD_FOR_PHRASE); + double desiredWidth = (double) Layout.getDesiredWidth(mText, mStart, + mEnd, mPaint, mTextDir); + int lineCount = (int) Math.ceil(desiredWidth / mWidth); + if (lineCount > 0 && lineCount <= lineLimit) { + return true; + } + return false; + } + + /** + * Get the line break word style. + * + * @return The current line break word style. + * + * @hide + */ + @VisibleForTesting + public int getLineBreakWordStyle() { + return mLineBreakConfig.getLineBreakWordStyle(); + } + private CharSequence mText; private int mStart; private int mEnd; diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java index 7ac6ae186cc3..51e36657e769 100644 --- a/core/java/android/text/TextUtils.java +++ b/core/java/android/text/TextUtils.java @@ -70,7 +70,6 @@ import android.util.Log; import android.util.Printer; import android.view.View; -import com.android.internal.R; import com.android.internal.util.ArrayUtils; import com.android.internal.util.Preconditions; @@ -1230,8 +1229,8 @@ public class TextUtils { /** * Transforms a CharSequences to uppercase, copying the sources spans and keeping them spans as - * much as possible close to their relative original places. In the case the the uppercase - * string is identical to the sources, the source itself is returned instead of being copied. + * much as possible close to their relative original places. If uppercase string is identical + * to the sources, the source itself is returned instead of being copied. * * If copySpans is set, source must be an instance of Spanned. * diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java index 3be4c3edc10e..a173d80288d5 100644 --- a/core/java/android/util/FeatureFlagUtils.java +++ b/core/java/android/util/FeatureFlagUtils.java @@ -74,6 +74,14 @@ public class FeatureFlagUtils { public static final String SETTINGS_HIDE_SECOND_LAYER_PAGE_NAVIGATE_UP_BUTTON_IN_TWO_PANE = "settings_hide_second_layer_page_navigate_up_button_in_two_pane"; + /** @hide */ + public static final String SETTINGS_AUTO_TEXT_WRAPPING = "settings_auto_text_wrapping"; + + /** Flag to enable/disable guest mode UX changes as mentioned in b/214031645 + * @hide + */ + public static final String SETTINGS_GUEST_MODE_UX_CHANGES = "settings_guest_mode_ux_changes"; + private static final Map<String, String> DEFAULT_FLAGS; static { @@ -100,6 +108,8 @@ public class FeatureFlagUtils { DEFAULT_FLAGS.put(SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS, "true"); DEFAULT_FLAGS.put(SETTINGS_APP_ALLOW_DARK_THEME_ACTIVATION_AT_BEDTIME, "true"); DEFAULT_FLAGS.put(SETTINGS_HIDE_SECOND_LAYER_PAGE_NAVIGATE_UP_BUTTON_IN_TWO_PANE, "true"); + DEFAULT_FLAGS.put(SETTINGS_AUTO_TEXT_WRAPPING, "false"); + DEFAULT_FLAGS.put(SETTINGS_GUEST_MODE_UX_CHANGES, "true"); } private static final Set<String> PERSISTENT_FLAGS; @@ -110,6 +120,7 @@ public class FeatureFlagUtils { PERSISTENT_FLAGS.add(SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS); PERSISTENT_FLAGS.add(SETTINGS_APP_ALLOW_DARK_THEME_ACTIVATION_AT_BEDTIME); PERSISTENT_FLAGS.add(SETTINGS_HIDE_SECOND_LAYER_PAGE_NAVIGATE_UP_BUTTON_IN_TWO_PANE); + PERSISTENT_FLAGS.add(SETTINGS_AUTO_TEXT_WRAPPING); } /** diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java index 0c4d9bf08583..3a684041e95c 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -26,11 +26,9 @@ import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SuppressLint; import android.annotation.TestApi; -import android.app.ActivityThread; import android.app.KeyguardManager; import android.app.WindowConfiguration; import android.compat.annotation.UnsupportedAppUsage; -import android.content.ComponentName; import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.content.res.Resources; @@ -52,14 +50,11 @@ import android.util.ArraySet; import android.util.DisplayMetrics; import android.util.Log; -import com.android.internal.R; - import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Optional; /** * Provides information about the size and density of a logical display. @@ -116,12 +111,6 @@ public final class Display { private int mCachedAppHeightCompat; /** - * Cache if the application is the recents component. - * TODO(b/179308296) Remove once Launcher addresses issue - */ - private Optional<Boolean> mIsRecentsComponent = Optional.empty(); - - /** * The default Display id, which is the id of the primary display assuming there is one. */ public static final int DEFAULT_DISPLAY = 0; @@ -576,7 +565,8 @@ public final class Display { * @see com.android.service.display.DisplayDevice#hasStableUniqueId(). * @hide */ - public String getUniqueId() { + @TestApi + public @Nullable String getUniqueId() { return mDisplayInfo.uniqueId; } @@ -1584,36 +1574,7 @@ public final class Display { return false; } final Configuration config = mResources.getConfiguration(); - // TODO(b/179308296) Temporarily exclude Launcher from being given max bounds, by checking - // if the caller is the recents component. - return config != null && !config.windowConfiguration.getMaxBounds().isEmpty() - && !isRecentsComponent(); - } - - /** - * Returns {@code true} when the calling package is the recents component. - * TODO(b/179308296) Remove once Launcher addresses issue - */ - boolean isRecentsComponent() { - if (mIsRecentsComponent.isPresent()) { - return mIsRecentsComponent.get(); - } - if (mResources == null) { - return false; - } - try { - String recentsComponent = mResources.getString(R.string.config_recentsComponentName); - if (recentsComponent == null) { - return false; - } - String recentsPackage = ComponentName.unflattenFromString(recentsComponent) - .getPackageName(); - mIsRecentsComponent = Optional.of(recentsPackage != null - && recentsPackage.equals(ActivityThread.currentPackageName())); - return mIsRecentsComponent.get(); - } catch (Resources.NotFoundException e) { - return false; - } + return config != null && !config.windowConfiguration.getMaxBounds().isEmpty(); } /** @@ -1631,6 +1592,21 @@ public final class Display { } /** + * Returns the committed state of the display. + * + * @return The latest committed display state, such as {@link #STATE_ON}. The display state + * {@link Display#getState()} is set as committed only after power state changes finish. + * + * @hide + */ + public int getCommittedState() { + synchronized (mLock) { + updateDisplayInfoLocked(); + return mIsValid ? mDisplayInfo.committedState : STATE_UNKNOWN; + } + } + + /** * Returns true if the specified UID has access to this display. * @hide */ diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java index 9264d2ed42a3..2aed319b1db9 100644 --- a/core/java/android/view/DisplayInfo.java +++ b/core/java/android/view/DisplayInfo.java @@ -253,6 +253,12 @@ public final class DisplayInfo implements Parcelable { public int state; /** + * The current committed state of the display. For example, this becomes + * {@link android.view.Display#STATE_ON} only after the power state ON is fully committed. + */ + public int committedState; + + /** * The UID of the application that owns this display, or zero if it is owned by the system. * <p> * If the display is private, then only the owner can use it. @@ -380,6 +386,7 @@ public final class DisplayInfo implements Parcelable { && appVsyncOffsetNanos == other.appVsyncOffsetNanos && presentationDeadlineNanos == other.presentationDeadlineNanos && state == other.state + && committedState == other.committedState && ownerUid == other.ownerUid && Objects.equals(ownerPackageName, other.ownerPackageName) && removeMode == other.removeMode @@ -431,6 +438,7 @@ public final class DisplayInfo implements Parcelable { appVsyncOffsetNanos = other.appVsyncOffsetNanos; presentationDeadlineNanos = other.presentationDeadlineNanos; state = other.state; + committedState = other.committedState; ownerUid = other.ownerUid; ownerPackageName = other.ownerPackageName; removeMode = other.removeMode; @@ -482,6 +490,7 @@ public final class DisplayInfo implements Parcelable { appVsyncOffsetNanos = source.readLong(); presentationDeadlineNanos = source.readLong(); state = source.readInt(); + committedState = source.readInt(); ownerUid = source.readInt(); ownerPackageName = source.readString8(); uniqueId = source.readString8(); @@ -538,6 +547,7 @@ public final class DisplayInfo implements Parcelable { dest.writeLong(appVsyncOffsetNanos); dest.writeLong(presentationDeadlineNanos); dest.writeInt(state); + dest.writeInt(committedState); dest.writeInt(ownerUid); dest.writeString8(ownerPackageName); dest.writeString8(uniqueId); @@ -761,6 +771,8 @@ public final class DisplayInfo implements Parcelable { sb.append(rotation); sb.append(", state "); sb.append(Display.stateToString(state)); + sb.append(", committedState "); + sb.append(Display.stateToString(committedState)); if (Process.myUid() != Process.SYSTEM_UID) { sb.append("}"); diff --git a/core/java/android/view/HandwritingInitiator.java b/core/java/android/view/HandwritingInitiator.java index 61098d60566f..3247bb7c6d38 100644 --- a/core/java/android/view/HandwritingInitiator.java +++ b/core/java/android/view/HandwritingInitiator.java @@ -19,6 +19,8 @@ package android.view; import android.annotation.NonNull; import android.annotation.Nullable; import android.graphics.Rect; +import android.util.DisplayMetrics; +import android.util.TypedValue; import android.view.inputmethod.InputMethodManager; import com.android.internal.annotations.VisibleForTesting; @@ -49,6 +51,12 @@ import java.util.List; * @hide */ public class HandwritingInitiator { + /** The amount of extra space added to handwriting in dip. */ + private static final int HANDWRITING_AREA_PADDING_DIP = 20; + + /** The amount of extra space added to handwriting in px. */ + private final float mHandwritingAreaPaddingPx; + /** * The touchSlop from {@link ViewConfiguration} used to decide whether a pointer is considered * moving or stationary. @@ -88,9 +96,13 @@ public class HandwritingInitiator { @VisibleForTesting public HandwritingInitiator(@NonNull ViewConfiguration viewConfiguration, - @NonNull InputMethodManager inputMethodManager) { + @NonNull InputMethodManager inputMethodManager, DisplayMetrics displayMetrics) { mTouchSlop = viewConfiguration.getScaledTouchSlop(); mHandwritingTimeoutInMillis = ViewConfiguration.getLongPressTimeout(); + mHandwritingAreaPaddingPx = TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, + HANDWRITING_AREA_PADDING_DIP, + displayMetrics); mImm = inputMethodManager; } @@ -250,7 +262,8 @@ public class HandwritingInitiator { } final Rect handwritingArea = getViewHandwritingArea(connectedView); - if (contains(handwritingArea, mState.mStylusDownX, mState.mStylusDownY)) { + if (containsInExtendedHandwritingArea(handwritingArea, + mState.mStylusDownX, mState.mStylusDownY)) { startHandwriting(connectedView); } else { reset(); @@ -281,14 +294,21 @@ public class HandwritingInitiator { */ @Nullable private View findBestCandidateView(float x, float y) { + float minDistance = Float.MAX_VALUE; + View bestCandidate = null; + // If the connectedView is not null and do not set any handwriting area, it will check // whether the connectedView's boundary contains the initial stylus position. If true, // directly return the connectedView. final View connectedView = getConnectedView(); if (connectedView != null && connectedView.isAutoHandwritingEnabled()) { - final Rect handwritingArea = getViewHandwritingArea(connectedView); - if (contains(handwritingArea, x, y)) { - return connectedView; + Rect handwritingArea = getViewHandwritingArea(connectedView); + if (containsInExtendedHandwritingArea(handwritingArea, x, y)) { + final float distance = distance(handwritingArea, x, y); + if (distance == 0f) return connectedView; + + bestCandidate = connectedView; + minDistance = distance; } } @@ -297,18 +317,78 @@ public class HandwritingInitiator { mHandwritingAreasTracker.computeViewInfos(); for (HandwritableViewInfo viewInfo : handwritableViewInfos) { final View view = viewInfo.getView(); - if (!view.isAutoHandwritingEnabled()) continue; - if (contains(viewInfo.getHandwritingArea(), x, y)) { - return viewInfo.getView(); + final Rect handwritingArea = viewInfo.getHandwritingArea(); + if (!containsInExtendedHandwritingArea(handwritingArea, x, y)) continue; + + final float distance = distance(handwritingArea, x, y); + + if (distance == 0f) return view; + if (distance < minDistance) { + minDistance = distance; + bestCandidate = view; } } - return null; + return bestCandidate; + } + + /** + * Return the square of the distance from point (x, y) to the given rect, which is mainly used + * for comparison. The distance is defined to be: the shortest distance between (x, y) to any + * point on rect. When (x, y) is contained by the rect, return 0f. + */ + private static float distance(@NonNull Rect rect, float x, float y) { + if (contains(rect, x, y, 0f, 0f, 0f, 0f)) { + return 0f; + } + + /* The distance between point (x, y) and rect, there are 2 basic cases: + * a) The distance is the distance from (x, y) to the closest corner on rect. + * o | | + * ---+-----+--- + * | | + * ---+-----+--- + * | | + * b) The distance is the distance from (x, y) to the closest edge on rect. + * | o | + * ---+-----+--- + * | | + * ---+-----+--- + * | | + * We define xDistance as following(similar for yDistance): + * If x is in [left, right) 0, else min(abs(x - left), abs(x - y)) + * For case a, sqrt(xDistance^2 + yDistance^2) is the final distance. + * For case b, distance should be yDistance, which is also equal to + * sqrt(xDistance^2 + yDistance^2) because xDistance is 0. + */ + final float xDistance; + if (x >= rect.left && x < rect.right) { + xDistance = 0f; + } else if (x < rect.left) { + xDistance = rect.left - x; + } else { + xDistance = x - rect.right; + } + + final float yDistance; + if (y >= rect.top && y < rect.bottom) { + yDistance = 0f; + } else if (y < rect.top) { + yDistance = rect.top - y; + } else { + yDistance = y - rect.bottom; + } + // We can omit sqrt here because we only need the distance for comparison. + return xDistance * xDistance + yDistance * yDistance; } /** * Return the handwriting area of the given view, represented in the window's coordinate. * If the view didn't set any handwriting area, it will return the view's boundary. * It will return null if the view or its handwriting area is not visible. + * + * The handwriting area is clipped to its visible part. + * Notice that the returned rectangle is the view's original handwriting area without the + * view's handwriting area extends. */ @Nullable private static Rect getViewHandwritingArea(@NonNull View view) { @@ -329,11 +409,24 @@ public class HandwritingInitiator { } /** - * Return true if the (x, y) is inside by the given {@link Rect}. + * Return true if the (x, y) is inside by the given {@link Rect} extended by the View's + * handwriting extends settings. + */ + private boolean containsInExtendedHandwritingArea(@Nullable Rect handwritingArea, + float x, float y) { + if (handwritingArea == null) return false; + return contains(handwritingArea, x, y, mHandwritingAreaPaddingPx, mHandwritingAreaPaddingPx, + mHandwritingAreaPaddingPx, mHandwritingAreaPaddingPx); + } + + /** + * Return true if the (x, y) is inside by the given {@link Rect} extended by the given + * extendLeft, extendTop, extendRight and extendBottom. */ - private boolean contains(@Nullable Rect rect, float x, float y) { - if (rect == null) return false; - return x >= rect.left && x < rect.right && y >= rect.top && y < rect.bottom; + private static boolean contains(@NonNull Rect rect, float x, float y, + float extendLeft, float extendTop, float extendRight, float extendBottom) { + return x >= rect.left - extendLeft && x < rect.right + extendRight + && y >= rect.top - extendTop && y < rect.bottom + extendBottom; } private boolean largerThanTouchSlop(float x1, float y1, float x2, float y2) { diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java index 7d5603994efa..addbab07c478 100644 --- a/core/java/android/view/InputDevice.java +++ b/core/java/android/view/InputDevice.java @@ -18,6 +18,7 @@ package android.view; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; @@ -517,6 +518,7 @@ public final class InputDevice implements Parcelable { * @param id The device id. * @return The input device or null if not found. */ + @Nullable public static InputDevice getDevice(int id) { return InputManager.getInstance().getInputDevice(id); } diff --git a/core/java/android/view/VelocityTracker.java b/core/java/android/view/VelocityTracker.java index 2b79bbfa72d4..f838d7fed7cf 100644 --- a/core/java/android/view/VelocityTracker.java +++ b/core/java/android/view/VelocityTracker.java @@ -17,9 +17,9 @@ package android.view; import android.annotation.IntDef; +import android.app.ActivityThread; import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; -import android.sysprop.InputProperties; import android.util.ArrayMap; import android.util.Pools.SynchronizedPool; @@ -278,8 +278,10 @@ public final class VelocityTracker { private VelocityTracker(@VelocityTrackerStrategy int strategy) { // If user has not selected a specific strategy if (strategy == VELOCITY_TRACKER_STRATEGY_DEFAULT) { + final String strategyProperty = ViewConfiguration.get( + ActivityThread.currentActivityThread().getApplication()) + .getVelocityTrackerStrategy(); // Check if user specified strategy by overriding system property. - String strategyProperty = InputProperties.velocitytracker_strategy().orElse(null); if (strategyProperty == null || strategyProperty.isEmpty()) { mStrategy = strategy; } else { diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index dc3620bcc5e5..71cc45f06027 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -31419,6 +31419,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * {@link android.view.inputmethod.InputMethodManager#startStylusHandwriting(View)} when there * is stylus movement detected. * + * Note that this attribute has no effect on the View's children. For example, if a + * {@link ViewGroup} disables auto handwriting but its children set auto handwriting to true, + * auto handwriting will still work for the children, and vice versa. + * * @see #onCreateInputConnection(EditorInfo) * @see android.view.inputmethod.InputMethodManager#startStylusHandwriting(View) * @param enabled whether auto handwriting initiation is enabled for this view. diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java index ebc409e470e9..30ae9c826f40 100644 --- a/core/java/android/view/ViewConfiguration.java +++ b/core/java/android/view/ViewConfiguration.java @@ -27,6 +27,7 @@ import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Rect; +import android.hardware.input.InputManager; import android.os.Build; import android.os.Bundle; import android.os.RemoteException; @@ -348,6 +349,7 @@ public class ViewConfiguration { private final int mSmartSelectionInitializedTimeout; private final int mSmartSelectionInitializingTimeout; private final int mPreferKeepClearForFocusDelay; + private final String mVelocityTrackerStrategy; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768915) private boolean sHasPermanentMenuKey; @@ -394,6 +396,7 @@ public class ViewConfiguration { mSmartSelectionInitializedTimeout = SMART_SELECTION_INITIALIZED_TIMEOUT_IN_MILLISECOND; mSmartSelectionInitializingTimeout = SMART_SELECTION_INITIALIZING_TIMEOUT_IN_MILLISECOND; mPreferKeepClearForFocusDelay = -1; + mVelocityTrackerStrategy = InputManager.getInstance().getVelocityTrackerStrategy(); } /** @@ -510,6 +513,16 @@ public class ViewConfiguration { com.android.internal.R.integer.config_smartSelectionInitializingTimeoutMillis); mPreferKeepClearForFocusDelay = res.getInteger( com.android.internal.R.integer.config_preferKeepClearForFocusDelayMillis); + + mVelocityTrackerStrategy = InputManager.getInstance().getVelocityTrackerStrategy(); + } + + /** + * Get the current VelocityTracker strategy + * @hide + */ + public String getVelocityTrackerStrategy() { + return mVelocityTrackerStrategy; } /** diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index fbb86ff3a55a..af5440aa6fdf 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -899,8 +899,10 @@ public final class ViewRootImpl implements ViewParent, ? Choreographer.getSfInstance() : Choreographer.getInstance(); mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE); mInsetsController = new InsetsController(new ViewRootInsetsControllerHost(this)); - mHandwritingInitiator = new HandwritingInitiator(mViewConfiguration, - mContext.getSystemService(InputMethodManager.class)); + mHandwritingInitiator = new HandwritingInitiator( + mViewConfiguration, + mContext.getSystemService(InputMethodManager.class), + context.getResources().getDisplayMetrics()); String processorOverrideName = context.getResources().getString( R.string.config_inputEventCompatProcessorOverrideClassName); @@ -2867,7 +2869,6 @@ public final class ViewRootImpl implements ViewParent, final int surfaceGenerationId = mSurface.getGenerationId(); final boolean isViewVisible = viewVisibility == View.VISIBLE; - final boolean windowRelayoutWasForced = mForceNextWindowRelayout; boolean surfaceSizeChanged = false; boolean surfaceCreated = false; boolean surfaceDestroyed = false; @@ -3041,8 +3042,7 @@ public final class ViewRootImpl implements ViewParent, if (isHardwareEnabled()) { mAttachInfo.mThreadedRenderer.destroy(); } - } else if ((surfaceReplaced - || surfaceSizeChanged || windowRelayoutWasForced) + } else if ((surfaceReplaced || surfaceSizeChanged) && mSurfaceHolder == null && mAttachInfo.mThreadedRenderer != null && mSurface.isValid()) { diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java index 90e349864092..ab17891a32dd 100644 --- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java +++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java @@ -3063,6 +3063,9 @@ public class AccessibilityNodeInfo implements Parcelable { int spanToReplaceStart = spannable.getSpanStart(span); int spanToReplaceEnd = spannable.getSpanEnd(span); int spanToReplaceFlags = spannable.getSpanFlags(span); + if (spanToReplaceStart < 0) { + continue; + } spannable.removeSpan(span); ClickableSpan replacementSpan = (span instanceof URLSpan) ? new AccessibilityURLSpan((URLSpan) span) @@ -3100,6 +3103,9 @@ public class AccessibilityNodeInfo implements Parcelable { int spanToReplaceStart = spannable.getSpanStart(span); int spanToReplaceEnd = spannable.getSpanEnd(span); int spanToReplaceFlags = spannable.getSpanFlags(span); + if (spanToReplaceStart < 0) { + continue; + } spannable.removeSpan(span); ReplacementSpan replacementSpan = new AccessibilityReplacementSpan(replacementText); spannable.setSpan(replacementSpan, spanToReplaceStart, spanToReplaceEnd, diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index 07756f638d4b..1220a66b4f99 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -27,6 +27,7 @@ import static android.view.autofill.Helper.sVerbose; import static android.view.autofill.Helper.toList; import android.accessibilityservice.AccessibilityServiceInfo; +import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -47,17 +48,22 @@ import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.graphics.Rect; import android.metrics.LogMaker; +import android.os.Binder; import android.os.Build; import android.os.Bundle; +import android.os.CancellationSignal; import android.os.Handler; import android.os.IBinder; +import android.os.ICancellationSignal; import android.os.Looper; import android.os.Parcelable; import android.os.RemoteException; import android.os.SystemClock; import android.provider.DeviceConfig; import android.service.autofill.AutofillService; +import android.service.autofill.FillCallback; import android.service.autofill.FillEventHistory; +import android.service.autofill.IFillCallback; import android.service.autofill.UserData; import android.text.TextUtils; import android.util.ArrayMap; @@ -78,6 +84,7 @@ import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeProvider; import android.view.accessibility.AccessibilityWindowInfo; +import android.view.inputmethod.InlineSuggestionsRequest; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; import android.widget.TextView; @@ -102,6 +109,7 @@ import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Set; +import java.util.concurrent.Executor; import sun.misc.Cleaner; @@ -170,6 +178,12 @@ import sun.misc.Cleaner; * shows an autofill save UI if the value of savable views have changed. If the user selects the * option to Save, the current value of the views is then sent to the autofill service. * + * <p>There is another choice for the application to provide it's datasets to the Autofill framework + * by setting an {@link AutofillRequestCallback} through + * {@link #setAutofillRequestCallback(Executor, AutofillRequestCallback)}. The application can use + * its callback instead of the default {@link AutofillService}. See + * {@link AutofillRequestCallback} for more details. + * * <h3 id="additional-notes">Additional notes</h3> * * <p>It is safe to call <code>AutofillManager</code> methods from any thread. @@ -295,6 +309,7 @@ public final class AutofillManager { /** @hide */ public static final int FLAG_ADD_CLIENT_DEBUG = 0x2; /** @hide */ public static final int FLAG_ADD_CLIENT_VERBOSE = 0x4; /** @hide */ public static final int FLAG_ADD_CLIENT_ENABLED_FOR_AUGMENTED_AUTOFILL_ONLY = 0x8; + /** @hide */ public static final int FLAG_ENABLED_CLIENT_SUGGESTIONS = 0x20; // NOTE: flag below is used by the session start receiver only, hence it can have values above /** @hide */ public static final int RECEIVER_FLAG_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY = 0x1; @@ -644,6 +659,11 @@ public final class AutofillManager { @GuardedBy("mLock") private boolean mEnabledForAugmentedAutofillOnly; + @GuardedBy("mLock") + @Nullable private AutofillRequestCallback mAutofillRequestCallback; + @GuardedBy("mLock") + @Nullable private Executor mRequestCallbackExecutor; + /** * Indicates whether there are any fields that need to do a fill request * after the activity starts. @@ -1999,6 +2019,32 @@ public final class AutofillManager { return new AutofillId(parent.getAutofillViewId(), virtualId); } + /** + * Sets the client's suggestions callback for autofill. + * + * @see AutofillRequestCallback + * + * @param executor specifies the thread upon which the callbacks will be invoked. + * @param callback which handles autofill request to provide client's suggestions. + */ + public void setAutofillRequestCallback(@NonNull @CallbackExecutor Executor executor, + @NonNull AutofillRequestCallback callback) { + synchronized (mLock) { + mRequestCallbackExecutor = executor; + mAutofillRequestCallback = callback; + } + } + + /** + * clears the client's suggestions callback for autofill. + */ + public void clearAutofillRequestCallback() { + synchronized (mLock) { + mRequestCallbackExecutor = null; + mAutofillRequestCallback = null; + } + } + @GuardedBy("mLock") private void startSessionLocked(@NonNull AutofillId id, @NonNull Rect bounds, @NonNull AutofillValue value, int flags) { @@ -2059,6 +2105,13 @@ public final class AutofillManager { } } + if (mAutofillRequestCallback != null) { + if (sDebug) { + Log.d(TAG, "startSession with the client suggestions provider"); + } + flags |= FLAG_ENABLED_CLIENT_SUGGESTIONS; + } + mService.startSession(client.autofillClientGetActivityToken(), mServiceClient.asBinder(), id, bounds, value, mContext.getUserId(), mCallback != null, flags, clientActivity, @@ -2412,6 +2465,28 @@ public final class AutofillManager { } } + private void onFillRequest(InlineSuggestionsRequest request, + CancellationSignal cancellationSignal, FillCallback callback) { + final AutofillRequestCallback autofillRequestCallback; + final Executor executor; + synchronized (mLock) { + autofillRequestCallback = mAutofillRequestCallback; + executor = mRequestCallbackExecutor; + } + if (autofillRequestCallback != null && executor != null) { + final long ident = Binder.clearCallingIdentity(); + try { + executor.execute(() -> + autofillRequestCallback.onFillRequest( + request, cancellationSignal, callback)); + } finally { + Binder.restoreCallingIdentity(ident); + } + } else { + callback.onSuccess(null); + } + } + /** @hide */ public static final int SET_STATE_FLAG_ENABLED = 0x01; /** @hide */ @@ -3901,6 +3976,23 @@ public final class AutofillManager { } } + @Override + public void requestFillFromClient(int id, InlineSuggestionsRequest request, + IFillCallback callback) { + final AutofillManager afm = mAfm.get(); + if (afm != null) { + ICancellationSignal transport = CancellationSignal.createTransport(); + try { + callback.onCancellable(transport); + } catch (RemoteException e) { + Slog.w(TAG, "Error requesting a cancellation", e); + } + + afm.onFillRequest(request, CancellationSignal.fromTransport(transport), + new FillCallback(callback, id)); + } + } + public void notifyFillDialogTriggerIds(List<AutofillId> ids) { final AutofillManager afm = mAfm.get(); if (afm != null) { diff --git a/core/java/android/view/autofill/AutofillRequestCallback.java b/core/java/android/view/autofill/AutofillRequestCallback.java new file mode 100644 index 000000000000..e632a5849471 --- /dev/null +++ b/core/java/android/view/autofill/AutofillRequestCallback.java @@ -0,0 +1,72 @@ +/* + * 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 android.view.autofill; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.os.CancellationSignal; +import android.service.autofill.FillCallback; +import android.view.inputmethod.InlineSuggestionsRequest; + +/** + * <p>This class is used to provide some input suggestions to the Autofill framework. + * + * <P>When the user is requested to input something, Autofill will try to query input suggestions + * for the user choosing. If the application want to provide some internal input suggestions, + * implements this callback and register via + * {@link AutofillManager#setAutofillRequestCallback(java.util.concurrent.Executor, + * AutofillRequestCallback)}. Autofill will callback the + * {@link #onFillRequest(InlineSuggestionsRequest, CancellationSignal, FillCallback)} to request + * input suggestions. + * + * <P>To make sure the callback to take effect, must register before the autofill session starts. + * If the autofill session is started, calls {@link AutofillManager#cancel()} to finish current + * session, and then the callback will be used at the next restarted session. + * + * <P>To create a {@link android.service.autofill.FillResponse}, application should fetch + * {@link AutofillId}s from its view structure. Below is an example: + * <pre class="prettyprint"> + * AutofillId usernameId = findViewById(R.id.username).getAutofillId(); + * AutofillId passwordId = findViewById(R.id.password).getAutofillId(); + * </pre> + * To learn more about creating a {@link android.service.autofill.FillResponse}, read + * <a href="/guide/topics/text/autofill-services#fill">Fill out client views</a>. + * + * <P>To fallback to the default {@link android.service.autofill.AutofillService}, just respond + * a null of the {@link android.service.autofill.FillResponse}. And then Autofill will do a fill + * request with the default {@link android.service.autofill.AutofillService}. Or clear the callback + * from {@link AutofillManager} via {@link AutofillManager#clearAutofillRequestCallback()}. If the + * client would like to keep no suggestions for the field, respond with an empty + * {@link android.service.autofill.FillResponse} which has no dataset. + * + * <P>IMPORTANT: This should not be used for displaying anything other than input suggestions, or + * the keyboard may choose to block your app from the inline strip. + */ +public interface AutofillRequestCallback { + /** + * Called by the Android system to decide if a screen can be autofilled by the callback. + * + * @param inlineSuggestionsRequest the {@link InlineSuggestionsRequest request} to handle if + * currently inline suggestions are supported and can be displayed. + * @param cancellationSignal signal for observing cancellation requests. The system will use + * this to notify you that the fill result is no longer needed and you should stop + * handling this fill request in order to save resources. + * @param callback object used to notify the result of the request. + */ + void onFillRequest(@Nullable InlineSuggestionsRequest inlineSuggestionsRequest, + @NonNull CancellationSignal cancellationSignal, @NonNull FillCallback callback); +} diff --git a/core/java/android/view/autofill/IAutoFillManagerClient.aidl b/core/java/android/view/autofill/IAutoFillManagerClient.aidl index 51afe4cf784d..2e5967cc32d1 100644 --- a/core/java/android/view/autofill/IAutoFillManagerClient.aidl +++ b/core/java/android/view/autofill/IAutoFillManagerClient.aidl @@ -24,9 +24,11 @@ import android.content.Intent; import android.content.IntentSender; import android.graphics.Rect; import android.os.IBinder; +import android.service.autofill.IFillCallback; import android.view.autofill.AutofillId; import android.view.autofill.AutofillValue; import android.view.autofill.IAutofillWindowPresenter; +import android.view.inputmethod.InlineSuggestionsRequest; import android.view.KeyEvent; import com.android.internal.os.IResultReceiver; @@ -142,6 +144,12 @@ oneway interface IAutoFillManagerClient { void requestShowSoftInput(in AutofillId id); /** + * Requests to determine if a screen can be autofilled by the client app. + */ + void requestFillFromClient(int id, in InlineSuggestionsRequest request, + in IFillCallback callback); + + /** * Notifies autofill ids that require to show the fill dialog. */ void notifyFillDialogTriggerIds(in List<AutofillId> ids); diff --git a/core/java/android/view/inputmethod/InlineSuggestionsRequest.java b/core/java/android/view/inputmethod/InlineSuggestionsRequest.java index c78b810f0b1f..70279cc8e845 100644 --- a/core/java/android/view/inputmethod/InlineSuggestionsRequest.java +++ b/core/java/android/view/inputmethod/InlineSuggestionsRequest.java @@ -111,6 +111,22 @@ public final class InlineSuggestionsRequest implements Parcelable { private @Nullable InlinePresentationSpec mInlineTooltipPresentationSpec; /** + * Whether the IME supports inline suggestions from the default Autofill service that + * provides the input view. + * + * Note: The default value is {@code true}. + */ + private boolean mServiceSupported; + + /** + * Whether the IME supports inline suggestions from the application that provides the + * input view. + * + * Note: The default value is {@code true}. + */ + private boolean mClientSupported; + + /** * @hide * @see {@link #mHostInputToken}. */ @@ -204,6 +220,14 @@ public final class InlineSuggestionsRequest implements Parcelable { return Bundle.EMPTY; } + private static boolean defaultServiceSupported() { + return true; + } + + private static boolean defaultClientSupported() { + return true; + } + /** @hide */ abstract static class BaseBuilder { abstract Builder setInlinePresentationSpecs( @@ -216,15 +240,25 @@ public final class InlineSuggestionsRequest implements Parcelable { abstract Builder setHostDisplayId(int value); } + /** @hide */ + public boolean isServiceSupported() { + return mServiceSupported; + } + + /** @hide */ + public boolean isClientSupported() { + return mClientSupported; + } + - // Code below generated by codegen v1.0.23. + // Code below generated by codegen v1.0.22. // // DO NOT MODIFY! // CHECKSTYLE:OFF Generated code // // To regenerate run: - // $ codegen $ANDROID_BUILD_TOP/./frameworks/base/core/java/android/view/inputmethod/InlineSuggestionsRequest.java + // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/view/inputmethod/InlineSuggestionsRequest.java // // To exclude the generated code from IntelliJ auto-formatting enable (one-time): // Settings > Editor > Code Style > Formatter Control @@ -240,7 +274,9 @@ public final class InlineSuggestionsRequest implements Parcelable { @NonNull Bundle extras, @Nullable IBinder hostInputToken, int hostDisplayId, - @Nullable InlinePresentationSpec inlineTooltipPresentationSpec) { + @Nullable InlinePresentationSpec inlineTooltipPresentationSpec, + boolean serviceSupported, + boolean clientSupported) { this.mMaxSuggestionCount = maxSuggestionCount; this.mInlinePresentationSpecs = inlinePresentationSpecs; com.android.internal.util.AnnotationValidations.validate( @@ -257,6 +293,8 @@ public final class InlineSuggestionsRequest implements Parcelable { this.mHostInputToken = hostInputToken; this.mHostDisplayId = hostDisplayId; this.mInlineTooltipPresentationSpec = inlineTooltipPresentationSpec; + this.mServiceSupported = serviceSupported; + this.mClientSupported = clientSupported; onConstructed(); } @@ -340,7 +378,9 @@ public final class InlineSuggestionsRequest implements Parcelable { } /** - * Specifies the UI specification for the inline suggestion tooltip in the response. + * The {@link InlinePresentationSpec} for the inline suggestion tooltip in the response. + * + * @see android.service.autofill.InlinePresentation#createTooltipPresentation(Slice, InlinePresentationSpec) */ @DataClass.Generated.Member public @Nullable InlinePresentationSpec getInlineTooltipPresentationSpec() { @@ -361,7 +401,9 @@ public final class InlineSuggestionsRequest implements Parcelable { "extras = " + mExtras + ", " + "hostInputToken = " + mHostInputToken + ", " + "hostDisplayId = " + mHostDisplayId + ", " + - "inlineTooltipPresentationSpec = " + mInlineTooltipPresentationSpec + + "inlineTooltipPresentationSpec = " + mInlineTooltipPresentationSpec + ", " + + "serviceSupported = " + mServiceSupported + ", " + + "clientSupported = " + mClientSupported + " }"; } @@ -385,7 +427,9 @@ public final class InlineSuggestionsRequest implements Parcelable { && extrasEquals(that.mExtras) && java.util.Objects.equals(mHostInputToken, that.mHostInputToken) && mHostDisplayId == that.mHostDisplayId - && java.util.Objects.equals(mInlineTooltipPresentationSpec, that.mInlineTooltipPresentationSpec); + && java.util.Objects.equals(mInlineTooltipPresentationSpec, that.mInlineTooltipPresentationSpec) + && mServiceSupported == that.mServiceSupported + && mClientSupported == that.mClientSupported; } @Override @@ -403,6 +447,8 @@ public final class InlineSuggestionsRequest implements Parcelable { _hash = 31 * _hash + java.util.Objects.hashCode(mHostInputToken); _hash = 31 * _hash + mHostDisplayId; _hash = 31 * _hash + java.util.Objects.hashCode(mInlineTooltipPresentationSpec); + _hash = 31 * _hash + Boolean.hashCode(mServiceSupported); + _hash = 31 * _hash + Boolean.hashCode(mClientSupported); return _hash; } @@ -413,6 +459,8 @@ public final class InlineSuggestionsRequest implements Parcelable { // void parcelFieldName(Parcel dest, int flags) { ... } int flg = 0; + if (mServiceSupported) flg |= 0x100; + if (mClientSupported) flg |= 0x200; if (mHostInputToken != null) flg |= 0x20; if (mInlineTooltipPresentationSpec != null) flg |= 0x80; dest.writeInt(flg); @@ -438,6 +486,8 @@ public final class InlineSuggestionsRequest implements Parcelable { // static FieldType unparcelFieldName(Parcel in) { ... } int flg = in.readInt(); + boolean serviceSupported = (flg & 0x100) != 0; + boolean clientSupported = (flg & 0x200) != 0; int maxSuggestionCount = in.readInt(); List<InlinePresentationSpec> inlinePresentationSpecs = new ArrayList<>(); in.readParcelableList(inlinePresentationSpecs, InlinePresentationSpec.class.getClassLoader(), android.widget.inline.InlinePresentationSpec.class); @@ -464,6 +514,8 @@ public final class InlineSuggestionsRequest implements Parcelable { this.mHostInputToken = hostInputToken; this.mHostDisplayId = hostDisplayId; this.mInlineTooltipPresentationSpec = inlineTooltipPresentationSpec; + this.mServiceSupported = serviceSupported; + this.mClientSupported = clientSupported; onConstructed(); } @@ -497,6 +549,8 @@ public final class InlineSuggestionsRequest implements Parcelable { private @Nullable IBinder mHostInputToken; private int mHostDisplayId; private @Nullable InlinePresentationSpec mInlineTooltipPresentationSpec; + private boolean mServiceSupported; + private boolean mClientSupported; private long mBuilderFieldsSet = 0L; @@ -629,7 +683,9 @@ public final class InlineSuggestionsRequest implements Parcelable { } /** - * Specifies the UI specification for the inline suggestion tooltip in the response. + * The {@link InlinePresentationSpec} for the inline suggestion tooltip in the response. + * + * @see android.service.autofill.InlinePresentation#createTooltipPresentation(Slice, InlinePresentationSpec)s */ @DataClass.Generated.Member public @NonNull Builder setInlineTooltipPresentationSpec(@NonNull InlinePresentationSpec value) { @@ -639,10 +695,38 @@ public final class InlineSuggestionsRequest implements Parcelable { return this; } + /** + * Whether the IME supports inline suggestions from the default Autofill service that + * provides the input view. + * + * Note: The default value is {@code true}. + */ + @DataClass.Generated.Member + public @NonNull Builder setServiceSupported(boolean value) { + checkNotUsed(); + mBuilderFieldsSet |= 0x100; + mServiceSupported = value; + return this; + } + + /** + * Whether the IME supports inline suggestions from the application that provides the + * input view. + * + * Note: The default value is {@code true}. + */ + @DataClass.Generated.Member + public @NonNull Builder setClientSupported(boolean value) { + checkNotUsed(); + mBuilderFieldsSet |= 0x200; + mClientSupported = value; + return this; + } + /** Builds the instance. This builder should not be touched after calling this! */ public @NonNull InlineSuggestionsRequest build() { checkNotUsed(); - mBuilderFieldsSet |= 0x100; // Mark builder used + mBuilderFieldsSet |= 0x400; // Mark builder used if ((mBuilderFieldsSet & 0x1) == 0) { mMaxSuggestionCount = defaultMaxSuggestionCount(); @@ -665,6 +749,12 @@ public final class InlineSuggestionsRequest implements Parcelable { if ((mBuilderFieldsSet & 0x80) == 0) { mInlineTooltipPresentationSpec = defaultInlineTooltipPresentationSpec(); } + if ((mBuilderFieldsSet & 0x100) == 0) { + mServiceSupported = defaultServiceSupported(); + } + if ((mBuilderFieldsSet & 0x200) == 0) { + mClientSupported = defaultClientSupported(); + } InlineSuggestionsRequest o = new InlineSuggestionsRequest( mMaxSuggestionCount, mInlinePresentationSpecs, @@ -673,12 +763,14 @@ public final class InlineSuggestionsRequest implements Parcelable { mExtras, mHostInputToken, mHostDisplayId, - mInlineTooltipPresentationSpec); + mInlineTooltipPresentationSpec, + mServiceSupported, + mClientSupported); return o; } private void checkNotUsed() { - if ((mBuilderFieldsSet & 0x100) != 0) { + if ((mBuilderFieldsSet & 0x400) != 0) { throw new IllegalStateException( "This Builder should not be reused. Use a new Builder instance instead"); } @@ -686,10 +778,10 @@ public final class InlineSuggestionsRequest implements Parcelable { } @DataClass.Generated( - time = 1621415989607L, - codegenVersion = "1.0.23", + time = 1615798784918L, + codegenVersion = "1.0.22", sourceFile = "frameworks/base/core/java/android/view/inputmethod/InlineSuggestionsRequest.java", - inputSignatures = "public static final int SUGGESTION_COUNT_UNLIMITED\nprivate final int mMaxSuggestionCount\nprivate final @android.annotation.NonNull java.util.List<android.widget.inline.InlinePresentationSpec> mInlinePresentationSpecs\nprivate @android.annotation.NonNull java.lang.String mHostPackageName\nprivate @android.annotation.NonNull android.os.LocaleList mSupportedLocales\nprivate @android.annotation.NonNull android.os.Bundle mExtras\nprivate @android.annotation.Nullable android.os.IBinder mHostInputToken\nprivate int mHostDisplayId\nprivate @android.annotation.Nullable android.widget.inline.InlinePresentationSpec mInlineTooltipPresentationSpec\nprivate static final @android.compat.annotation.ChangeId @android.compat.annotation.EnabledSince long IME_AUTOFILL_DEFAULT_SUPPORTED_LOCALES_IS_EMPTY\npublic void setHostInputToken(android.os.IBinder)\nprivate boolean extrasEquals(android.os.Bundle)\nprivate void parcelHostInputToken(android.os.Parcel,int)\nprivate @android.annotation.Nullable android.os.IBinder unparcelHostInputToken(android.os.Parcel)\npublic void setHostDisplayId(int)\nprivate void onConstructed()\npublic void filterContentTypes()\nprivate static int defaultMaxSuggestionCount()\nprivate static java.lang.String defaultHostPackageName()\nprivate static android.widget.inline.InlinePresentationSpec defaultInlineTooltipPresentationSpec()\nprivate static android.os.LocaleList defaultSupportedLocales()\nprivate static @android.annotation.Nullable android.os.IBinder defaultHostInputToken()\nprivate static @android.annotation.Nullable int defaultHostDisplayId()\nprivate static @android.annotation.NonNull android.os.Bundle defaultExtras()\nclass InlineSuggestionsRequest extends java.lang.Object implements [android.os.Parcelable]\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setInlinePresentationSpecs(java.util.List<android.widget.inline.InlinePresentationSpec>)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostPackageName(java.lang.String)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostInputToken(android.os.IBinder)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostDisplayId(int)\nclass BaseBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genBuilder=true)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setInlinePresentationSpecs(java.util.List<android.widget.inline.InlinePresentationSpec>)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostPackageName(java.lang.String)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostInputToken(android.os.IBinder)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostDisplayId(int)\nclass BaseBuilder extends java.lang.Object implements []") + inputSignatures = "public static final int SUGGESTION_COUNT_UNLIMITED\nprivate final int mMaxSuggestionCount\nprivate final @android.annotation.NonNull java.util.List<android.widget.inline.InlinePresentationSpec> mInlinePresentationSpecs\nprivate @android.annotation.NonNull java.lang.String mHostPackageName\nprivate @android.annotation.NonNull android.os.LocaleList mSupportedLocales\nprivate @android.annotation.NonNull android.os.Bundle mExtras\nprivate @android.annotation.Nullable android.os.IBinder mHostInputToken\nprivate int mHostDisplayId\nprivate @android.annotation.Nullable android.widget.inline.InlinePresentationSpec mInlineTooltipPresentationSpec\nprivate boolean mServiceSupported\nprivate boolean mClientSupported\nprivate static final @android.compat.annotation.ChangeId @android.compat.annotation.EnabledSince long IME_AUTOFILL_DEFAULT_SUPPORTED_LOCALES_IS_EMPTY\npublic void setHostInputToken(android.os.IBinder)\nprivate boolean extrasEquals(android.os.Bundle)\nprivate void parcelHostInputToken(android.os.Parcel,int)\nprivate @android.annotation.Nullable android.os.IBinder unparcelHostInputToken(android.os.Parcel)\npublic void setHostDisplayId(int)\nprivate void onConstructed()\npublic void filterContentTypes()\nprivate static int defaultMaxSuggestionCount()\nprivate static java.lang.String defaultHostPackageName()\nprivate static android.widget.inline.InlinePresentationSpec defaultInlineTooltipPresentationSpec()\nprivate static android.os.LocaleList defaultSupportedLocales()\nprivate static @android.annotation.Nullable android.os.IBinder defaultHostInputToken()\nprivate static @android.annotation.Nullable int defaultHostDisplayId()\nprivate static @android.annotation.NonNull android.os.Bundle defaultExtras()\nprivate static boolean defaultServiceSupported()\nprivate static boolean defaultClientSupported()\npublic boolean isServiceSupported()\npublic boolean isClientSupported()\nclass InlineSuggestionsRequest extends java.lang.Object implements [android.os.Parcelable]\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setInlinePresentationSpecs(java.util.List<android.widget.inline.InlinePresentationSpec>)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostPackageName(java.lang.String)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostInputToken(android.os.IBinder)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostDisplayId(int)\nclass BaseBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genBuilder=true)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setInlinePresentationSpecs(java.util.List<android.widget.inline.InlinePresentationSpec>)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostPackageName(java.lang.String)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostInputToken(android.os.IBinder)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostDisplayId(int)\nclass BaseBuilder extends java.lang.Object implements []") @Deprecated private void __metadata() {} diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index 84f13930e03a..3fd6ae7a41cf 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -2923,7 +2923,8 @@ public final class InputMethodManager { */ @Deprecated public void hideSoftInputFromInputMethod(IBinder token, int flags) { - InputMethodPrivilegedOperationsRegistry.get(token).hideMySoftInput(flags); + InputMethodPrivilegedOperationsRegistry.get(token).hideMySoftInput( + flags, SoftInputShowHideReason.HIDE_SOFT_INPUT_IMM_DEPRECATION); } /** diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 231ae084dd6c..184e7bca963b 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -4363,8 +4363,35 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te final int delta = Math.round(axisValue * mVerticalScrollFactor); if (delta != 0) { + // If we're moving down, we want the top item. If we're moving up, bottom item. + final int motionIndex = delta > 0 ? 0 : getChildCount() - 1; + + int motionViewPrevTop = 0; + View motionView = this.getChildAt(motionIndex); + if (motionView != null) { + motionViewPrevTop = motionView.getTop(); + } + + final int overscrollMode = getOverScrollMode(); + if (!trackMotionScroll(delta, delta)) { return true; + } else if (!event.isFromSource(InputDevice.SOURCE_MOUSE) && motionView != null + && (overscrollMode == OVER_SCROLL_ALWAYS + || (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS + && !contentFits()))) { + int motionViewRealTop = motionView.getTop(); + float overscroll = (delta - (motionViewRealTop - motionViewPrevTop)) + / ((float) getHeight()); + if (delta > 0) { + mEdgeGlowTop.onPullDistance(overscroll, 0.5f); + mEdgeGlowTop.onRelease(); + } else { + mEdgeGlowBottom.onPullDistance(-overscroll, 0.5f); + mEdgeGlowBottom.onRelease(); + } + invalidate(); + return true; } } break; diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java index 018cba7f95e5..2dbfd7e5b2e2 100644 --- a/core/java/android/widget/HorizontalScrollView.java +++ b/core/java/android/widget/HorizontalScrollView.java @@ -872,15 +872,39 @@ public class HorizontalScrollView extends FrameLayout { final int range = getScrollRange(); int oldScrollX = mScrollX; int newScrollX = oldScrollX + delta; + + final int overscrollMode = getOverScrollMode(); + boolean canOverscroll = !event.isFromSource(InputDevice.SOURCE_MOUSE) + && (overscrollMode == OVER_SCROLL_ALWAYS + || (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && range > 0)); + boolean absorbed = false; + if (newScrollX < 0) { + if (canOverscroll) { + mEdgeGlowLeft.onPullDistance(-(float) newScrollX / getWidth(), + 0.5f); + mEdgeGlowLeft.onRelease(); + invalidate(); + absorbed = true; + } newScrollX = 0; } else if (newScrollX > range) { + if (canOverscroll) { + mEdgeGlowRight.onPullDistance( + (float) (newScrollX - range) / getWidth(), 0.5f); + mEdgeGlowRight.onRelease(); + invalidate(); + absorbed = true; + } newScrollX = range; } if (newScrollX != oldScrollX) { super.scrollTo(newScrollX, mScrollY); return true; } + if (absorbed) { + return true; + } } } } diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java index 8e293f4b356d..61a7599e8f73 100644 --- a/core/java/android/widget/RemoteViewsAdapter.java +++ b/core/java/android/widget/RemoteViewsAdapter.java @@ -52,9 +52,9 @@ import android.widget.RemoteViews.InteractionHandler; import com.android.internal.widget.IRemoteViewsFactory; import java.lang.ref.WeakReference; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; -import java.util.LinkedList; import java.util.concurrent.Executor; /** @@ -424,17 +424,17 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback * adapter that have not yet had their RemoteViews loaded. */ private class RemoteViewsFrameLayoutRefSet - extends SparseArray<LinkedList<RemoteViewsFrameLayout>> { + extends SparseArray<ArrayList<RemoteViewsFrameLayout>> { /** * Adds a new reference to a RemoteViewsFrameLayout returned by the adapter. */ public void add(int position, RemoteViewsFrameLayout layout) { - LinkedList<RemoteViewsFrameLayout> refs = get(position); + ArrayList<RemoteViewsFrameLayout> refs = get(position); // Create the list if necessary if (refs == null) { - refs = new LinkedList<>(); + refs = new ArrayList<>(); put(position, refs); } @@ -451,7 +451,7 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback if (view == null) return; // Remove this set from the original mapping - final LinkedList<RemoteViewsFrameLayout> refs = removeReturnOld(position); + final ArrayList<RemoteViewsFrameLayout> refs = removeReturnOld(position); if (refs != null) { // Notify all the references for that position of the newly loaded RemoteViews for (final RemoteViewsFrameLayout ref : refs) { @@ -467,7 +467,7 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback if (rvfl.cacheIndex < 0) { return; } - final LinkedList<RemoteViewsFrameLayout> refs = get(rvfl.cacheIndex); + final ArrayList<RemoteViewsFrameLayout> refs = get(rvfl.cacheIndex); if (refs != null) { refs.remove(rvfl); } @@ -933,12 +933,8 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback Runnable r = () -> { synchronized (sCachedRemoteViewsCaches) { - if (sCachedRemoteViewsCaches.containsKey(key)) { - sCachedRemoteViewsCaches.remove(key); - } - if (sRemoteViewsCacheRemoveRunnables.containsKey(key)) { - sRemoteViewsCacheRemoveRunnables.remove(key); - } + sCachedRemoteViewsCaches.remove(key); + sRemoteViewsCacheRemoveRunnables.remove(key); } }; sRemoteViewsCacheRemoveRunnables.put(key, r); diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java index 15cd17b20f4f..2acd50c9e169 100644 --- a/core/java/android/widget/ScrollView.java +++ b/core/java/android/widget/ScrollView.java @@ -939,15 +939,38 @@ public class ScrollView extends FrameLayout { final int range = getScrollRange(); int oldScrollY = mScrollY; int newScrollY = oldScrollY - delta; + + final int overscrollMode = getOverScrollMode(); + boolean canOverscroll = !event.isFromSource(InputDevice.SOURCE_MOUSE) + && (overscrollMode == OVER_SCROLL_ALWAYS + || (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && range > 0)); + boolean absorbed = false; + if (newScrollY < 0) { + if (canOverscroll) { + mEdgeGlowTop.onPullDistance(-(float) newScrollY / getHeight(), 0.5f); + mEdgeGlowTop.onRelease(); + invalidate(); + absorbed = true; + } newScrollY = 0; } else if (newScrollY > range) { + if (canOverscroll) { + mEdgeGlowBottom.onPullDistance( + (float) (newScrollY - range) / getHeight(), 0.5f); + mEdgeGlowBottom.onRelease(); + invalidate(); + absorbed = true; + } newScrollY = range; } if (newScrollY != oldScrollY) { super.scrollTo(mScrollX, newScrollY); return true; } + if (absorbed) { + return true; + } } break; } diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 93f72640bd3f..a91597527472 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -144,6 +144,7 @@ import android.text.style.UpdateAppearance; import android.text.util.Linkify; import android.util.AttributeSet; import android.util.DisplayMetrics; +import android.util.FeatureFlagUtils; import android.util.IntArray; import android.util.Log; import android.util.SparseIntArray; @@ -791,6 +792,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private int mLineBreakStyle = DEFAULT_LINE_BREAK_STYLE; private int mLineBreakWordStyle = DEFAULT_LINE_BREAK_WORD_STYLE; + // The auto option for LINE_BREAK_WORD_STYLE_PHRASE may not be applied in recycled view due to + // one-way flag flipping. This is a tentative limitation during experiment and will not have the + // issue once this is finalized to LINE_BREAK_WORD_STYLE_PHRASE_AUTO option. + private boolean mUserSpeficiedLineBreakwordStyle = false; + // This is used to reflect the current user preference for changing font weight and making text // more bold. private int mFontWeightAdjustment; @@ -1462,6 +1468,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener break; case com.android.internal.R.styleable.TextView_lineBreakWordStyle: + if (a.hasValue(attr)) { + mUserSpeficiedLineBreakwordStyle = true; + } mLineBreakWordStyle = a.getInt(attr, LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE); break; @@ -4209,6 +4218,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener break; case com.android.internal.R.styleable.TextAppearance_lineBreakWordStyle: attributes.mHasLineBreakWordStyle = true; + mUserSpeficiedLineBreakwordStyle = true; attributes.mLineBreakWordStyle = appearance.getInt(attr, attributes.mLineBreakWordStyle); break; @@ -4910,6 +4920,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @param lineBreakWordStyle the line break word style for the tet */ public void setLineBreakWordStyle(@LineBreakConfig.LineBreakWordStyle int lineBreakWordStyle) { + mUserSpeficiedLineBreakwordStyle = true; if (mLineBreakWordStyle != lineBreakWordStyle) { mLineBreakWordStyle = lineBreakWordStyle; if (mLayout != null) { @@ -4945,8 +4956,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @see PrecomputedText */ public @NonNull PrecomputedText.Params getTextMetricsParams() { + final boolean autoPhraseBreaking = + !mUserSpeficiedLineBreakwordStyle && FeatureFlagUtils.isEnabled(mContext, + FeatureFlagUtils.SETTINGS_AUTO_TEXT_WRAPPING); return new PrecomputedText.Params(new TextPaint(mTextPaint), - LineBreakConfig.getLineBreakConfig(mLineBreakStyle, mLineBreakWordStyle), + LineBreakConfig.getLineBreakConfig(mLineBreakStyle, mLineBreakWordStyle, + autoPhraseBreaking), getTextDirectionHeuristic(), mBreakStrategy, mHyphenationFrequency); } @@ -4966,6 +4981,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener LineBreakConfig lineBreakConfig = params.getLineBreakConfig(); mLineBreakStyle = lineBreakConfig.getLineBreakStyle(); mLineBreakWordStyle = lineBreakConfig.getLineBreakWordStyle(); + mUserSpeficiedLineBreakwordStyle = true; if (mLayout != null) { nullLayouts(); requestLayout(); @@ -6502,10 +6518,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (mTextDir == null) { mTextDir = getTextDirectionHeuristic(); } + final boolean autoPhraseBreaking = + !mUserSpeficiedLineBreakwordStyle && FeatureFlagUtils.isEnabled(mContext, + FeatureFlagUtils.SETTINGS_AUTO_TEXT_WRAPPING); final @PrecomputedText.Params.CheckResultUsableResult int checkResult = precomputed.getParams().checkResultUsable(getPaint(), mTextDir, mBreakStrategy, mHyphenationFrequency, LineBreakConfig.getLineBreakConfig( - mLineBreakStyle, mLineBreakWordStyle)); + mLineBreakStyle, mLineBreakWordStyle, autoPhraseBreaking)); switch (checkResult) { case PrecomputedText.Params.UNUSABLE: throw new IllegalArgumentException( @@ -9403,6 +9422,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } // TODO: code duplication with makeSingleLayout() if (mHintLayout == null) { + final boolean autoPhraseBreaking = + !mUserSpeficiedLineBreakwordStyle && FeatureFlagUtils.isEnabled(mContext, + FeatureFlagUtils.SETTINGS_AUTO_TEXT_WRAPPING); StaticLayout.Builder builder = StaticLayout.Builder.obtain(mHint, 0, mHint.length(), mTextPaint, hintWidth) .setAlignment(alignment) @@ -9415,7 +9437,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener .setJustificationMode(mJustificationMode) .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE) .setLineBreakConfig(LineBreakConfig.getLineBreakConfig( - mLineBreakStyle, mLineBreakWordStyle)); + mLineBreakStyle, mLineBreakWordStyle, autoPhraseBreaking)); if (shouldEllipsize) { builder.setEllipsize(mEllipsize) .setEllipsizedWidth(ellipsisWidth); @@ -9519,6 +9541,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } if (result == null) { + final boolean autoPhraseBreaking = + !mUserSpeficiedLineBreakwordStyle && FeatureFlagUtils.isEnabled(mContext, + FeatureFlagUtils.SETTINGS_AUTO_TEXT_WRAPPING); StaticLayout.Builder builder = StaticLayout.Builder.obtain(mTransformed, 0, mTransformed.length(), mTextPaint, wantWidth) .setAlignment(alignment) @@ -9531,7 +9556,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener .setJustificationMode(mJustificationMode) .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE) .setLineBreakConfig(LineBreakConfig.getLineBreakConfig( - mLineBreakStyle, mLineBreakWordStyle)); + mLineBreakStyle, mLineBreakWordStyle, autoPhraseBreaking)); if (shouldEllipsize) { builder.setEllipsize(effectiveEllipsize) .setEllipsizedWidth(ellipsisWidth); @@ -9889,7 +9914,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener final StaticLayout.Builder layoutBuilder = StaticLayout.Builder.obtain( text, 0, text.length(), mTempTextPaint, Math.round(availableSpace.right)); - + final boolean autoPhraseBreaking = + !mUserSpeficiedLineBreakwordStyle && FeatureFlagUtils.isEnabled(mContext, + FeatureFlagUtils.SETTINGS_AUTO_TEXT_WRAPPING); layoutBuilder.setAlignment(getLayoutAlignment()) .setLineSpacing(getLineSpacingExtra(), getLineSpacingMultiplier()) .setIncludePad(getIncludeFontPadding()) @@ -9900,7 +9927,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE) .setTextDirection(getTextDirectionHeuristic()) .setLineBreakConfig(LineBreakConfig.getLineBreakConfig( - mLineBreakStyle, mLineBreakWordStyle)); + mLineBreakStyle, mLineBreakWordStyle, autoPhraseBreaking)); final StaticLayout layout = layoutBuilder.build(); diff --git a/core/java/com/android/internal/app/AbstractResolverComparator.java b/core/java/com/android/internal/app/AbstractResolverComparator.java index 42fc7bd6e6fc..975954035c17 100644 --- a/core/java/com/android/internal/app/AbstractResolverComparator.java +++ b/core/java/com/android/internal/app/AbstractResolverComparator.java @@ -228,12 +228,6 @@ public abstract class AbstractResolverComparator implements Comparator<ResolvedC */ abstract float getScore(ComponentName name); - /** - * Returns the list of top K component names which have highest - * {@link #getScore(ComponentName)} - */ - abstract List<ComponentName> getTopComponentNames(int topK); - /** Handles result message sent to mHandler. */ abstract void handleResultMessage(Message message); diff --git a/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java b/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java index bc9eff04636d..115a9d772658 100644 --- a/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java +++ b/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java @@ -33,12 +33,12 @@ import android.util.Log; import com.android.internal.app.ResolverActivity.ResolvedComponentInfo; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.concurrent.Executors; -import java.util.stream.Collectors; /** * Uses an {@link AppPredictor} to sort Resolver targets. If the AppPredictionService appears to be @@ -51,13 +51,16 @@ class AppPredictionServiceResolverComparator extends AbstractResolverComparator private final AppPredictor mAppPredictor; private final Context mContext; - private final Map<ComponentName, Integer> mTargetRanks = new HashMap<>(); - private final Map<ComponentName, Integer> mTargetScores = new HashMap<>(); private final UserHandle mUser; private final Intent mIntent; private final String mReferrerPackage; + + private final ModelBuilder mModelBuilder; + private ResolverComparatorModel mComparatorModel; + // If this is non-null (and this is not destroyed), it means APS is disabled and we should fall // back to using the ResolverRankerService. + // TODO: responsibility for this fallback behavior can live outside of the AppPrediction client. private ResolverRankerServiceResolverComparator mResolverRankerService; AppPredictionServiceResolverComparator( @@ -74,25 +77,48 @@ class AppPredictionServiceResolverComparator extends AbstractResolverComparator mUser = user; mReferrerPackage = referrerPackage; setChooserActivityLogger(chooserActivityLogger); + + mModelBuilder = new ModelBuilder(appPredictor, user); + mComparatorModel = mModelBuilder.buildFromRankedList(Collections.emptyList()); } @Override - int compare(ResolveInfo lhs, ResolveInfo rhs) { + void destroy() { if (mResolverRankerService != null) { - return mResolverRankerService.compare(lhs, rhs); + mResolverRankerService.destroy(); + mResolverRankerService = null; + + // TODO: may not be necessary to build a new model, since we're destroying anyways. + mComparatorModel = mModelBuilder.buildFallbackModel(mResolverRankerService); } - Integer lhsRank = mTargetRanks.get(new ComponentName(lhs.activityInfo.packageName, - lhs.activityInfo.name)); - Integer rhsRank = mTargetRanks.get(new ComponentName(rhs.activityInfo.packageName, - rhs.activityInfo.name)); - if (lhsRank == null && rhsRank == null) { - return 0; - } else if (lhsRank == null) { - return -1; - } else if (rhsRank == null) { - return 1; + } + + @Override + int compare(ResolveInfo lhs, ResolveInfo rhs) { + return mComparatorModel.getComparator().compare(lhs, rhs); + } + + @Override + float getScore(ComponentName name) { + return mComparatorModel.getScore(name); + } + + @Override + void updateModel(ComponentName componentName) { + mComparatorModel.notifyOnTargetSelected(componentName); + } + + @Override + void handleResultMessage(Message msg) { + // Null value is okay if we have defaulted to the ResolverRankerService. + if (msg.what == RANKER_SERVICE_RESULT && msg.obj != null) { + // TODO: this probably never happens? The sorting callback circumvents the Handler + // design to call handleResult() directly instead of sending the list through a Message. + // (OK to leave as-is since the Handler design is going away soon.) + mComparatorModel = mModelBuilder.buildFromRankedList((List<AppTarget>) msg.obj); + } else if (msg.obj == null && mResolverRankerService == null) { + Log.e(TAG, "Unexpected null result"); } - return lhsRank - rhsRank; } @Override @@ -115,111 +141,155 @@ class AppPredictionServiceResolverComparator extends AbstractResolverComparator sortedAppTargets -> { if (sortedAppTargets.isEmpty()) { Log.i(TAG, "AppPredictionService disabled. Using resolver."); - // APS for chooser is disabled. Fallback to resolver. - mResolverRankerService = - new ResolverRankerServiceResolverComparator( - mContext, mIntent, mReferrerPackage, - () -> mHandler.sendEmptyMessage(RANKER_SERVICE_RESULT), - getChooserActivityLogger()); - mResolverRankerService.compute(targets); + setupFallbackModel(targets); } else { Log.i(TAG, "AppPredictionService response received"); // Skip sending to Handler which takes extra time to dispatch messages. + // TODO: the Handler guards some concurrency conditions, so this could + // probably result in a race (we're not currently on the Handler thread?). + // We'll leave this as-is since we intend to remove the Handler design + // shortly, but this is still an unsound shortcut. handleResult(sortedAppTargets); } } ); } - @Override - void handleResultMessage(Message msg) { - // Null value is okay if we have defaulted to the ResolverRankerService. - if (msg.what == RANKER_SERVICE_RESULT && msg.obj != null) { - final List<AppTarget> sortedAppTargets = (List<AppTarget>) msg.obj; - handleSortedAppTargets(sortedAppTargets); - } else if (msg.obj == null && mResolverRankerService == null) { - Log.e(TAG, "Unexpected null result"); - } + private void setupFallbackModel(List<ResolvedComponentInfo> targets) { + mResolverRankerService = + new ResolverRankerServiceResolverComparator( + mContext, mIntent, mReferrerPackage, + () -> mHandler.sendEmptyMessage(RANKER_SERVICE_RESULT), + getChooserActivityLogger()); + mComparatorModel = mModelBuilder.buildFallbackModel(mResolverRankerService); + mResolverRankerService.compute(targets); } private void handleResult(List<AppTarget> sortedAppTargets) { if (mHandler.hasMessages(RANKER_RESULT_TIMEOUT)) { - handleSortedAppTargets(sortedAppTargets); + mComparatorModel = mModelBuilder.buildFromRankedList(sortedAppTargets); mHandler.removeMessages(RANKER_RESULT_TIMEOUT); afterCompute(); } } - private void handleSortedAppTargets(List<AppTarget> sortedAppTargets) { - if (checkAppTargetRankValid(sortedAppTargets)) { - sortedAppTargets.forEach(target -> mTargetScores.put( - new ComponentName(target.getPackageName(), target.getClassName()), - target.getRank())); + static class ModelBuilder { + private final AppPredictor mAppPredictor; + private final UserHandle mUser; + + ModelBuilder(AppPredictor appPredictor, UserHandle user) { + mAppPredictor = appPredictor; + mUser = user; } - for (int i = 0; i < sortedAppTargets.size(); i++) { - ComponentName componentName = new ComponentName( - sortedAppTargets.get(i).getPackageName(), - sortedAppTargets.get(i).getClassName()); - mTargetRanks.put(componentName, i); - Log.i(TAG, "handleSortedAppTargets, sortedAppTargets #" + i + ": " + componentName); + + ResolverComparatorModel buildFromRankedList(List<AppTarget> sortedAppTargets) { + return new AppPredictionServiceComparatorModel( + mAppPredictor, mUser, buildTargetRanksMapFromSortedTargets(sortedAppTargets)); } - } - private boolean checkAppTargetRankValid(List<AppTarget> sortedAppTargets) { - for (AppTarget target : sortedAppTargets) { - if (target.getRank() != 0) { - return true; - } + ResolverComparatorModel buildFallbackModel( + ResolverRankerServiceResolverComparator fallback) { + return adaptLegacyResolverComparatorToComparatorModel(fallback); } - return false; - } - @Override - float getScore(ComponentName name) { - if (mResolverRankerService != null) { - return mResolverRankerService.getScore(name); + // The remaining methods would be static if this weren't an inner class (i.e., they don't + // depend on any ivars, not even the ones in ModelBuilder). + + private Map<ComponentName, Integer> buildTargetRanksMapFromSortedTargets( + List<AppTarget> sortedAppTargets) { + Map<ComponentName, Integer> targetRanks = new HashMap<>(); + for (int i = 0; i < sortedAppTargets.size(); i++) { + ComponentName componentName = new ComponentName( + sortedAppTargets.get(i).getPackageName(), + sortedAppTargets.get(i).getClassName()); + targetRanks.put(componentName, i); + Log.i(TAG, "handleSortedAppTargets, sortedAppTargets #" + i + ": " + componentName); + } + return targetRanks; } - Integer rank = mTargetRanks.get(name); - if (rank == null) { - Log.w(TAG, "Score requested for unknown component. Did you call compute yet?"); - return 0f; + + // TODO: when the refactoring is further along we'll probably have access to the + // comparator's new ResolverComparatorModel API, so we won't have to adapt from the legacy + // interface here. On the other hand, AppPredictionServiceResolverComparatorModel (or its + // replacement counterpart) shouldn't still be responsible for implementing the + // ResolverRankerService fallback logic at that time. + private ResolverComparatorModel adaptLegacyResolverComparatorToComparatorModel( + AbstractResolverComparator comparator) { + return new ResolverComparatorModel() { + @Override + public Comparator<ResolveInfo> getComparator() { + // Adapt the base type, which doesn't declare itself to be an implementation + // of {@code Comparator<ResolveInfo>} even though it has the one method. + return (lhs, rhs) -> comparator.compare(lhs, rhs); + } + + @Override + public float getScore(ComponentName componentName) { + return comparator.getScore(componentName); + } + + @Override + public void notifyOnTargetSelected(ComponentName componentName) { + comparator.updateModel(componentName); + } + }; } - int consecutiveSumOfRanks = (mTargetRanks.size() - 1) * (mTargetRanks.size()) / 2; - return 1.0f - (((float) rank) / consecutiveSumOfRanks); } - @Override - List<ComponentName> getTopComponentNames(int topK) { - if (mResolverRankerService != null) { - return mResolverRankerService.getTopComponentNames(topK); + // TODO: Finish separating behaviors of AbstractResolverComparator, then (probably) make this a + // standalone class once clients are written in terms of ResolverComparatorModel. + static class AppPredictionServiceComparatorModel implements ResolverComparatorModel { + private final AppPredictor mAppPredictor; + private final UserHandle mUser; + private final Map<ComponentName, Integer> mTargetRanks; // Treat as immutable. + + AppPredictionServiceComparatorModel( + AppPredictor appPredictor, + UserHandle user, + Map<ComponentName, Integer> targetRanks) { + mAppPredictor = appPredictor; + mUser = user; + mTargetRanks = targetRanks; } - return mTargetRanks.entrySet().stream() - .sorted(Entry.comparingByValue()) - .limit(topK) - .map(Entry::getKey) - .collect(Collectors.toList()); - } - @Override - void updateModel(ComponentName componentName) { - if (mResolverRankerService != null) { - mResolverRankerService.updateModel(componentName); - return; + @Override + public Comparator<ResolveInfo> getComparator() { + return (lhs, rhs) -> { + Integer lhsRank = mTargetRanks.get(new ComponentName(lhs.activityInfo.packageName, + lhs.activityInfo.name)); + Integer rhsRank = mTargetRanks.get(new ComponentName(rhs.activityInfo.packageName, + rhs.activityInfo.name)); + if (lhsRank == null && rhsRank == null) { + return 0; + } else if (lhsRank == null) { + return -1; + } else if (rhsRank == null) { + return 1; + } + return lhsRank - rhsRank; + }; } - mAppPredictor.notifyAppTargetEvent( - new AppTargetEvent.Builder( - new AppTarget.Builder( - new AppTargetId(componentName.toString()), - componentName.getPackageName(), mUser) - .setClassName(componentName.getClassName()).build(), - ACTION_LAUNCH).build()); - } - @Override - void destroy() { - if (mResolverRankerService != null) { - mResolverRankerService.destroy(); - mResolverRankerService = null; + @Override + public float getScore(ComponentName name) { + Integer rank = mTargetRanks.get(name); + if (rank == null) { + Log.w(TAG, "Score requested for unknown component. Did you call compute yet?"); + return 0f; + } + int consecutiveSumOfRanks = (mTargetRanks.size() - 1) * (mTargetRanks.size()) / 2; + return 1.0f - (((float) rank) / consecutiveSumOfRanks); + } + + @Override + public void notifyOnTargetSelected(ComponentName componentName) { + mAppPredictor.notifyAppTargetEvent( + new AppTargetEvent.Builder( + new AppTarget.Builder( + new AppTargetId(componentName.toString()), + componentName.getPackageName(), mUser) + .setClassName(componentName.getClassName()).build(), + ACTION_LAUNCH).build()); } } } diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index 49ee91c4c2a7..3cb39e725214 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -194,9 +194,6 @@ public class ChooserActivity extends ResolverActivity implements private static final String PLURALS_COUNT = "count"; private static final String PLURALS_FILE_NAME = "file_name"; - @VisibleForTesting - public static final int LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS = 250; - private boolean mIsAppPredictorComponentAvailable; private Map<ChooserTarget, AppTarget> mDirectShareAppTargetCache; private Map<ChooserTarget, ShortcutInfo> mDirectShareShortcutInfoCache; @@ -248,6 +245,13 @@ public class ChooserActivity extends ResolverActivity implements SystemUiDeviceConfigFlags.IS_NEARBY_SHARE_FIRST_TARGET_IN_RANKED_APP, DEFAULT_IS_NEARBY_SHARE_FIRST_TARGET_IN_RANKED_APP); + private static final int DEFAULT_LIST_VIEW_UPDATE_DELAY_MS = 250; + + @VisibleForTesting + int mListViewUpdateDelayMs = DeviceConfig.getInt(DeviceConfig.NAMESPACE_SYSTEMUI, + SystemUiDeviceConfigFlags.SHARESHEET_LIST_VIEW_UPDATE_DELAY, + DEFAULT_LIST_VIEW_UPDATE_DELAY_MS); + private Bundle mReplacementExtras; private IntentSender mChosenComponentSender; private IntentSender mRefinementIntentSender; @@ -2624,7 +2628,7 @@ public class ChooserActivity extends ResolverActivity implements Message msg = Message.obtain(); msg.what = ChooserHandler.LIST_VIEW_UPDATE_MESSAGE; msg.obj = userHandle; - mChooserHandler.sendMessageDelayed(msg, LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS); + mChooserHandler.sendMessageDelayed(msg, mListViewUpdateDelayMs); } @Override diff --git a/core/java/com/android/internal/app/ResolverComparatorModel.java b/core/java/com/android/internal/app/ResolverComparatorModel.java new file mode 100644 index 000000000000..3e8f64bf4ed3 --- /dev/null +++ b/core/java/com/android/internal/app/ResolverComparatorModel.java @@ -0,0 +1,57 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.app; + +import android.content.ComponentName; +import android.content.pm.ResolveInfo; + +import java.util.Comparator; +import java.util.List; + +/** + * A ranking model for resolver targets, providing ordering and (optionally) numerical scoring. + * + * As required by the {@link Comparator} contract, objects returned by {@code getComparator()} must + * apply a total ordering on its inputs consistent across all calls to {@code Comparator#compare()}. + * Other query methods and ranking feedback should refer to that same ordering, so implementors are + * generally advised to "lock in" an immutable snapshot of their model data when this object is + * initialized (preferring to replace the entire {@code ResolverComparatorModel} instance if the + * backing data needs to be updated in the future). + */ +interface ResolverComparatorModel { + /** + * Get a {@code Comparator} that can be used to sort {@code ResolveInfo} targets according to + * the model ranking. + */ + Comparator<ResolveInfo> getComparator(); + + /** + * Get the numerical score, if any, that the model assigns to the component with the specified + * {@code name}. Scores range from zero to one, with one representing the highest possible + * likelihood that the user will select that component as the target. Implementations that don't + * assign numerical scores are <em>recommended</em> to return a value of 0 for all components. + */ + float getScore(ComponentName name); + + /** + * Notify the model that the user selected a target. (Models may log this information, use it as + * a feedback signal for their ranking, etc.) Because the data in this + * {@code ResolverComparatorModel} instance is immutable, clients will need to get an up-to-date + * instance in order to see any changes in the ranking that might result from this feedback. + */ + void notifyOnTargetSelected(ComponentName componentName); +} diff --git a/core/java/com/android/internal/app/ResolverListAdapter.java b/core/java/com/android/internal/app/ResolverListAdapter.java index ac9b2d8a8d8f..351ac4587def 100644 --- a/core/java/com/android/internal/app/ResolverListAdapter.java +++ b/core/java/com/android/internal/app/ResolverListAdapter.java @@ -155,14 +155,6 @@ public class ResolverListAdapter extends BaseAdapter { return mResolverListController.getScore(componentName); } - /** - * Returns the list of top K component names which have highest - * {@link #getScore(DisplayResolveInfo)} - */ - public List<ComponentName> getTopComponentNames(int topK) { - return mResolverListController.getTopComponentNames(topK); - } - public void updateModel(ComponentName componentName) { mResolverListController.updateModel(componentName); } @@ -177,107 +169,206 @@ public class ResolverListAdapter extends BaseAdapter { } /** - * Rebuild the list of resolvers. In some cases some parts will need some asynchronous work - * to complete. + * Rebuild the list of resolvers. When rebuilding is complete, queue the {@code onPostListReady} + * callback on the main handler with {@code rebuildCompleted} true. + * + * In some cases some parts will need some asynchronous work to complete. Then this will first + * immediately queue {@code onPostListReady} (on the main handler) with {@code rebuildCompleted} + * false; only when the asynchronous work completes will this then go on to queue another + * {@code onPostListReady} callback with {@code rebuildCompleted} true. * - * The {@code doPostProcessing } parameter is used to specify whether to update the UI and - * load additional targets (e.g. direct share) after the list has been rebuilt. This is used - * in the case where we want to load the inactive profile's resolved apps to know the + * The {@code doPostProcessing} parameter is used to specify whether to update the UI and + * load additional targets (e.g. direct share) after the list has been rebuilt. We may choose + * to skip that step if we're only loading the inactive profile's resolved apps to know the * number of targets. * - * @return Whether or not the list building is completed. + * @return Whether the list building was completed synchronously. If not, we'll queue the + * {@code onPostListReady} callback first with {@code rebuildCompleted} false, and then again + * with {@code rebuildCompleted} true at the end of some newly-launched asynchronous work. + * Otherwise the callback is only queued once, with {@code rebuildCompleted} true. */ protected boolean rebuildList(boolean doPostProcessing) { - List<ResolvedComponentInfo> currentResolveList = null; - // Clear the value of mOtherProfile from previous call. - mOtherProfile = null; - mLastChosen = null; - mLastChosenPosition = -1; mDisplayList.clear(); mIsTabLoaded = false; + mLastChosenPosition = -1; + + List<ResolvedComponentInfo> currentResolveList = getInitialRebuiltResolveList(); + + /* TODO: this seems like unnecessary extra complexity; why do we need to do this "primary" + * (i.e. "eligibility") filtering before evaluating the "other profile" special-treatment, + * but the "secondary" (i.e. "priority") filtering after? Are there in fact cases where the + * eligibility conditions will filter out a result that would've otherwise gotten the "other + * profile" treatment? Or, are there cases where the priority conditions *would* filter out + * a result, but we *want* that result to get the "other profile" treatment, so we only + * filter *after* evaluating the special-treatment conditions? If the answer to either is + * "no," then the filtering steps can be consolidated. (And that also makes the "unfiltered + * list" bookkeeping a little cleaner.) + */ + mUnfilteredResolveList = performPrimaryResolveListFiltering(currentResolveList); + // So far we only support a single other profile at a time. + // The first one we see gets special treatment. + ResolvedComponentInfo otherProfileInfo = + getFirstNonCurrentUserResolvedComponentInfo(currentResolveList); + updateOtherProfileTreatment(otherProfileInfo); + if (otherProfileInfo != null) { + currentResolveList.remove(otherProfileInfo); + /* TODO: the previous line removed the "other profile info" item from + * mUnfilteredResolveList *ONLY IF* that variable is an alias for the same List instance + * as currentResolveList (i.e., if no items were filtered out as the result of the + * earlier "primary" filtering). It seems wrong for our behavior to depend on that. + * Should we: + * A. replicate the above removal to mUnfilteredResolveList (which is idempotent, so we + * don't even have to check whether they're aliases); or + * B. break the alias relationship by copying currentResolveList to a new + * mUnfilteredResolveList instance if necessary before removing otherProfileInfo? + * In other words: do we *want* otherProfileInfo in the "unfiltered" results? Either + * way, we'll need one of the changes suggested above. + */ + } + + // If no results have yet been filtered, mUnfilteredResolveList is an alias for the same + // List instance as currentResolveList. Then we need to make a copy to store as the + // mUnfilteredResolveList if we go on to filter any more items. Otherwise we've already + // copied the original unfiltered items to a separate List instance and can now filter + // the remainder in-place without any further bookkeeping. + boolean needsCopyOfUnfiltered = (mUnfilteredResolveList == currentResolveList); + mUnfilteredResolveList = performSecondaryResolveListFiltering( + currentResolveList, needsCopyOfUnfiltered); + + return finishRebuildingListWithFilteredResults(currentResolveList, doPostProcessing); + } + + /** + * Get the full (unfiltered) set of {@code ResolvedComponentInfo} records for all resolvers + * to be considered in a newly-rebuilt list. This list will be filtered and ranked before the + * rebuild is complete. + */ + List<ResolvedComponentInfo> getInitialRebuiltResolveList() { if (mBaseResolveList != null) { - currentResolveList = mUnfilteredResolveList = new ArrayList<>(); + List<ResolvedComponentInfo> currentResolveList = new ArrayList<>(); mResolverListController.addResolveListDedupe(currentResolveList, mResolverListCommunicator.getTargetIntent(), mBaseResolveList); + return currentResolveList; } else { - currentResolveList = mUnfilteredResolveList = - mResolverListController.getResolversForIntent( + return mResolverListController.getResolversForIntent( /* shouldGetResolvedFilter= */ true, mResolverListCommunicator.shouldGetActivityMetadata(), mIntents); - if (currentResolveList == null) { - processSortedList(currentResolveList, doPostProcessing); - return true; - } - List<ResolvedComponentInfo> originalList = - mResolverListController.filterIneligibleActivities(currentResolveList, - true); - if (originalList != null) { - mUnfilteredResolveList = originalList; - } } + } - // So far we only support a single other profile at a time. - // The first one we see gets special treatment. - for (ResolvedComponentInfo info : currentResolveList) { - ResolveInfo resolveInfo = info.getResolveInfoAt(0); - if (resolveInfo.targetUserId != UserHandle.USER_CURRENT) { - Intent pOrigIntent = mResolverListCommunicator.getReplacementIntent( - resolveInfo.activityInfo, - info.getIntentAt(0)); - Intent replacementIntent = mResolverListCommunicator.getReplacementIntent( - resolveInfo.activityInfo, - mResolverListCommunicator.getTargetIntent()); - mOtherProfile = new DisplayResolveInfo(info.getIntentAt(0), - resolveInfo, - resolveInfo.loadLabel(mPm), - resolveInfo.loadLabel(mPm), - pOrigIntent != null ? pOrigIntent : replacementIntent, - makePresentationGetter(resolveInfo)); - currentResolveList.remove(info); - break; - } + /** + * Remove ineligible activities from {@code currentResolveList} (if non-null), in-place. More + * broadly, filtering logic should apply in the "primary" stage if it should preclude items from + * receiving the "other profile" special-treatment described in {@code rebuildList()}. + * + * @return A copy of the original {@code currentResolveList}, if any items were removed, or a + * (possibly null) reference to the original list otherwise. (That is, this always returns a + * list of all the unfiltered items, but if no items were filtered, it's just an alias for the + * same list that was passed in). + */ + @Nullable + List<ResolvedComponentInfo> performPrimaryResolveListFiltering( + @Nullable List<ResolvedComponentInfo> currentResolveList) { + /* TODO: mBaseResolveList appears to be(?) some kind of configured mode. Why is it not + * subject to filterIneligibleActivities, even though all the other logic still applies + * (including "secondary" filtering)? (This also relates to the earlier question; do we + * believe there's an item that would be eligible for "other profile" special treatment, + * except we want to filter it out as ineligible... but only if we're not in + * "mBaseResolveList mode"? */ + if ((mBaseResolveList != null) || (currentResolveList == null)) { + return currentResolveList; + } + + List<ResolvedComponentInfo> originalList = + mResolverListController.filterIneligibleActivities(currentResolveList, true); + return (originalList == null) ? currentResolveList : originalList; + } + + /** + * Remove low-priority activities from {@code currentResolveList} (if non-null), in place. More + * broadly, filtering logic should apply in the "secondary" stage to prevent items from + * appearing in the rebuilt-list results, while still considering those items for the "other + * profile" special-treatment described in {@code rebuildList()}. + * + * @return the same (possibly null) List reference as {@code currentResolveList}, if the list is + * unmodified as a result of filtering; or, if some item(s) were removed, then either a copy of + * the original {@code currentResolveList} (if {@code returnCopyOfOriginalListIfModified} is + * true), or null (otherwise). + */ + @Nullable + List<ResolvedComponentInfo> performSecondaryResolveListFiltering( + @Nullable List<ResolvedComponentInfo> currentResolveList, + boolean returnCopyOfOriginalListIfModified) { + if ((currentResolveList == null) || currentResolveList.isEmpty()) { + return currentResolveList; } + return mResolverListController.filterLowPriority( + currentResolveList, returnCopyOfOriginalListIfModified); + } + + /** + * Update the special "other profile" UI treatment based on the components resolved for a + * newly-built list. + * + * @param otherProfileInfo the first {@code ResolvedComponentInfo} specifying a + * {@code targetUserId} other than {@code USER_CURRENT}, or null if no such component info was + * found in the process of rebuilding the list (or if any such candidates were already removed + * due to "primary filtering"). + */ + void updateOtherProfileTreatment(@Nullable ResolvedComponentInfo otherProfileInfo) { + mLastChosen = null; - if (mOtherProfile == null) { + if (otherProfileInfo != null) { + mOtherProfile = makeOtherProfileDisplayResolveInfo( + mContext, otherProfileInfo, mPm, mResolverListCommunicator, mIconDpi); + } else { + mOtherProfile = null; try { mLastChosen = mResolverListController.getLastChosen(); + // TODO: does this also somehow need to update mLastChosenPosition? If so, maybe + // the current method should also take responsibility for re-initializing + // mLastChosenPosition, where it's currently done at the start of rebuildList()? + // (Why is this related to the presence of mOtherProfile in fhe first place?) } catch (RemoteException re) { Log.d(TAG, "Error calling getLastChosenActivity\n" + re); } } + } - setPlaceholderCount(0); - int n; - if ((currentResolveList != null) && ((n = currentResolveList.size()) > 0)) { - // We only care about fixing the unfilteredList if the current resolve list and - // current resolve list are currently the same. - List<ResolvedComponentInfo> originalList = - mResolverListController.filterLowPriority(currentResolveList, - mUnfilteredResolveList == currentResolveList); - if (originalList != null) { - mUnfilteredResolveList = originalList; - } - - if (currentResolveList.size() > 1) { - int placeholderCount = currentResolveList.size(); - if (mResolverListCommunicator.useLayoutWithDefault()) { - --placeholderCount; - } - setPlaceholderCount(placeholderCount); - createSortingTask(doPostProcessing).execute(currentResolveList); - postListReadyRunnable(doPostProcessing, /* rebuildCompleted */ false); - return false; - } else { - processSortedList(currentResolveList, doPostProcessing); - return true; - } - } else { - processSortedList(currentResolveList, doPostProcessing); + /** + * Prepare the appropriate placeholders to eventually display the final set of resolved + * components in a newly-rebuilt list, and spawn an asynchronous sorting task if necessary. + * This eventually results in a {@code onPostListReady} callback with {@code rebuildCompleted} + * true; if any asynchronous work is required, that will first be preceded by a separate + * occurrence of the callback with {@code rebuildCompleted} false (once there are placeholders + * set up to represent the pending asynchronous results). + * @return Whether we were able to do all the work to prepare the list for display + * synchronously; if false, there will eventually be two separate {@code onPostListReady} + * callbacks, first with placeholders to represent pending asynchronous results, then later when + * the results are ready for presentation. + */ + boolean finishRebuildingListWithFilteredResults( + @Nullable List<ResolvedComponentInfo> filteredResolveList, boolean doPostProcessing) { + if (filteredResolveList == null || filteredResolveList.size() < 2) { + // No asynchronous work to do. + setPlaceholderCount(0); + processSortedList(filteredResolveList, doPostProcessing); return true; } + + int placeholderCount = filteredResolveList.size(); + if (mResolverListCommunicator.useLayoutWithDefault()) { + --placeholderCount; + } + setPlaceholderCount(placeholderCount); + + // Send an "incomplete" list-ready while the async task is running. + postListReadyRunnable(doPostProcessing, /* rebuildCompleted */ false); + createSortingTask(doPostProcessing).execute(filteredResolveList); + return false; } AsyncTask<List<ResolvedComponentInfo>, @@ -644,6 +735,59 @@ public class ResolverListAdapter extends BaseAdapter { } /** + * Find the first element in a list of {@code ResolvedComponentInfo} objects whose + * {@code ResolveInfo} specifies a {@code targetUserId} other than the current user. + * @return the first ResolvedComponentInfo targeting a non-current user, or null if there are + * none (or if the list itself is null). + */ + private static ResolvedComponentInfo getFirstNonCurrentUserResolvedComponentInfo( + @Nullable List<ResolvedComponentInfo> resolveList) { + if (resolveList == null) { + return null; + } + + for (ResolvedComponentInfo info : resolveList) { + ResolveInfo resolveInfo = info.getResolveInfoAt(0); + if (resolveInfo.targetUserId != UserHandle.USER_CURRENT) { + return info; + } + } + return null; + } + + /** + * Set up a {@code DisplayResolveInfo} to provide "special treatment" for the first "other" + * profile in the resolve list (i.e., the first non-current profile to appear as the target user + * of an element in the resolve list). + */ + private static DisplayResolveInfo makeOtherProfileDisplayResolveInfo( + Context context, + ResolvedComponentInfo resolvedComponentInfo, + PackageManager pm, + ResolverListCommunicator resolverListCommunicator, + int iconDpi) { + ResolveInfo resolveInfo = resolvedComponentInfo.getResolveInfoAt(0); + + Intent pOrigIntent = resolverListCommunicator.getReplacementIntent( + resolveInfo.activityInfo, + resolvedComponentInfo.getIntentAt(0)); + Intent replacementIntent = resolverListCommunicator.getReplacementIntent( + resolveInfo.activityInfo, + resolverListCommunicator.getTargetIntent()); + + ResolveInfoPresentationGetter presentationGetter = + new ResolveInfoPresentationGetter(context, iconDpi, resolveInfo); + + return new DisplayResolveInfo( + resolvedComponentInfo.getIntentAt(0), + resolveInfo, + resolveInfo.loadLabel(pm), + resolveInfo.loadLabel(pm), + pOrigIntent != null ? pOrigIntent : replacementIntent, + presentationGetter); + } + + /** * Necessary methods to communicate between {@link ResolverListAdapter} * and {@link ResolverActivity}. */ diff --git a/core/java/com/android/internal/app/ResolverListController.java b/core/java/com/android/internal/app/ResolverListController.java index 9a95e6411fa4..27573631b2ce 100644 --- a/core/java/com/android/internal/app/ResolverListController.java +++ b/core/java/com/android/internal/app/ResolverListController.java @@ -393,14 +393,6 @@ public class ResolverListController { return mResolverComparator.getScore(componentName); } - /** - * Returns the list of top K component names which have highest - * {@link #getScore(DisplayResolveInfo)} - */ - public List<ComponentName> getTopComponentNames(int topK) { - return mResolverComparator.getTopComponentNames(topK); - } - public void updateModel(ComponentName componentName) { mResolverComparator.updateModel(componentName); } diff --git a/core/java/com/android/internal/app/ResolverRankerServiceResolverComparator.java b/core/java/com/android/internal/app/ResolverRankerServiceResolverComparator.java index cb946c0dcf99..c5b21ac4da90 100644 --- a/core/java/com/android/internal/app/ResolverRankerServiceResolverComparator.java +++ b/core/java/com/android/internal/app/ResolverRankerServiceResolverComparator.java @@ -43,12 +43,12 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import java.text.Collator; import java.util.ArrayList; +import java.util.Comparator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; /** * Ranks and compares packages based on usage stats and uses the {@link ResolverRankerService}. @@ -83,6 +83,7 @@ class ResolverRankerServiceResolverComparator extends AbstractResolverComparator private ResolverRankerServiceConnection mConnection; private Context mContext; private CountDownLatch mConnectSignal; + private ResolverRankerServiceComparatorModel mComparatorModel; public ResolverRankerServiceResolverComparator(Context context, Intent intent, String referrerPackage, AfterCompute afterCompute, @@ -99,6 +100,8 @@ class ResolverRankerServiceResolverComparator extends AbstractResolverComparator mRankerServiceName = new ComponentName(mContext, this.getClass()); setCallBack(afterCompute); setChooserActivityLogger(chooserActivityLogger); + + mComparatorModel = buildUpdatedModel(); } @Override @@ -125,6 +128,7 @@ class ResolverRankerServiceResolverComparator extends AbstractResolverComparator } if (isUpdated) { mRankerServiceName = mResolvedRankerName; + mComparatorModel = buildUpdatedModel(); } } else { Log.e(TAG, "Sizes of sent and received ResolverTargets diff."); @@ -218,83 +222,25 @@ class ResolverRankerServiceResolverComparator extends AbstractResolverComparator } } predictSelectProbabilities(mTargets); + + mComparatorModel = buildUpdatedModel(); } @Override public int compare(ResolveInfo lhs, ResolveInfo rhs) { - if (mStats != null) { - final ResolverTarget lhsTarget = mTargetsDict.get(new ComponentName( - lhs.activityInfo.packageName, lhs.activityInfo.name)); - final ResolverTarget rhsTarget = mTargetsDict.get(new ComponentName( - rhs.activityInfo.packageName, rhs.activityInfo.name)); - - if (lhsTarget != null && rhsTarget != null) { - final int selectProbabilityDiff = Float.compare( - rhsTarget.getSelectProbability(), lhsTarget.getSelectProbability()); - - if (selectProbabilityDiff != 0) { - return selectProbabilityDiff > 0 ? 1 : -1; - } - } - } - - CharSequence sa = lhs.loadLabel(mPm); - if (sa == null) sa = lhs.activityInfo.name; - CharSequence sb = rhs.loadLabel(mPm); - if (sb == null) sb = rhs.activityInfo.name; - - return mCollator.compare(sa.toString().trim(), sb.toString().trim()); + return mComparatorModel.getComparator().compare(lhs, rhs); } @Override public float getScore(ComponentName name) { - final ResolverTarget target = mTargetsDict.get(name); - if (target != null) { - return target.getSelectProbability(); - } - return 0; - } - - @Override - List<ComponentName> getTopComponentNames(int topK) { - return mTargetsDict.entrySet().stream() - .sorted((o1, o2) -> -Float.compare(getScore(o1.getKey()), getScore(o2.getKey()))) - .limit(topK) - .map(Map.Entry::getKey) - .collect(Collectors.toList()); + return mComparatorModel.getScore(name); } // update ranking model when the connection to it is valid. @Override public void updateModel(ComponentName componentName) { synchronized (mLock) { - if (mRanker != null) { - try { - int selectedPos = new ArrayList<ComponentName>(mTargetsDict.keySet()) - .indexOf(componentName); - if (selectedPos >= 0 && mTargets != null) { - final float selectedProbability = getScore(componentName); - int order = 0; - for (ResolverTarget target : mTargets) { - if (target.getSelectProbability() > selectedProbability) { - order++; - } - } - logMetrics(order); - mRanker.train(mTargets, selectedPos); - } else { - if (DEBUG) { - Log.d(TAG, "Selected a unknown component: " + componentName); - } - } - } catch (RemoteException e) { - Log.e(TAG, "Error in Train: " + e); - } - } else { - if (DEBUG) { - Log.d(TAG, "Ranker is null; skip updateModel."); - } - } + mComparatorModel.notifyOnTargetSelected(componentName); } } @@ -313,19 +259,6 @@ class ResolverRankerServiceResolverComparator extends AbstractResolverComparator } } - // records metrics for evaluation. - private void logMetrics(int selectedPos) { - if (mRankerServiceName != null) { - MetricsLogger metricsLogger = new MetricsLogger(); - LogMaker log = new LogMaker(MetricsEvent.ACTION_TARGET_SELECTED); - log.setComponentName(mRankerServiceName); - int isCategoryUsed = (mAnnotations == null) ? 0 : 1; - log.addTaggedData(MetricsEvent.FIELD_IS_CATEGORY_USED, isCategoryUsed); - log.addTaggedData(MetricsEvent.FIELD_RANKED_POSITION, selectedPos); - metricsLogger.write(log); - } - } - // connect to a ranking service. private void initRanker(Context context) { synchronized (mLock) { @@ -426,6 +359,7 @@ class ResolverRankerServiceResolverComparator extends AbstractResolverComparator } synchronized (mLock) { mRanker = IResolverRankerService.Stub.asInterface(service); + mComparatorModel = buildUpdatedModel(); mConnectSignal.countDown(); } } @@ -443,6 +377,7 @@ class ResolverRankerServiceResolverComparator extends AbstractResolverComparator public void destroy() { synchronized (mLock) { mRanker = null; + mComparatorModel = buildUpdatedModel(); } } } @@ -453,6 +388,7 @@ class ResolverRankerServiceResolverComparator extends AbstractResolverComparator mTargetsDict.clear(); mTargets = null; mRankerServiceName = new ComponentName(mContext, this.getClass()); + mComparatorModel = buildUpdatedModel(); mResolvedRankerName = null; initRanker(mContext); } @@ -508,4 +444,155 @@ class ResolverRankerServiceResolverComparator extends AbstractResolverComparator } return false; } + + /** + * Re-construct a {@code ResolverRankerServiceComparatorModel} to replace the current model + * instance (if any) using the up-to-date {@code ResolverRankerServiceResolverComparator} ivar + * values. + * + * TODO: each time we replace the model instance, we're either updating the model to use + * adjusted data (which is appropriate), or we're providing a (late) value for one of our ivars + * that wasn't available the last time the model was updated. For those latter cases, we should + * just avoid creating the model altogether until we have all the prerequisites we'll need. Then + * we can probably simplify the logic in {@code ResolverRankerServiceComparatorModel} since we + * won't need to handle edge cases when the model data isn't fully prepared. + * (In some cases, these kinds of "updates" might interleave -- e.g., we might have finished + * initializing the first time and now want to adjust some data, but still need to wait for + * changes to propagate to the other ivars before rebuilding the model.) + */ + private ResolverRankerServiceComparatorModel buildUpdatedModel() { + // TODO: we don't currently guarantee that the underlying target list/map won't be mutated, + // so the ResolverComparatorModel may provide inconsistent results. We should make immutable + // copies of the data (waiting for any necessary remaining data before creating the model). + return new ResolverRankerServiceComparatorModel( + mStats, + mTargetsDict, + mTargets, + mCollator, + mRanker, + mRankerServiceName, + (mAnnotations != null), + mPm); + } + + /** + * Implementation of a {@code ResolverComparatorModel} that provides the same ranking logic as + * the legacy {@code ResolverRankerServiceResolverComparator}, as a refactoring step toward + * removing the complex legacy API. + */ + static class ResolverRankerServiceComparatorModel implements ResolverComparatorModel { + private final Map<String, UsageStats> mStats; // Treat as immutable. + private final Map<ComponentName, ResolverTarget> mTargetsDict; // Treat as immutable. + private final List<ResolverTarget> mTargets; // Treat as immutable. + private final Collator mCollator; + private final IResolverRankerService mRanker; + private final ComponentName mRankerServiceName; + private final boolean mAnnotationsUsed; + private final PackageManager mPm; + + // TODO: it doesn't look like we should have to pass both targets and targetsDict, but it's + // not written in a way that makes it clear whether we can derive one from the other (at + // least in this constructor). + ResolverRankerServiceComparatorModel( + Map<String, UsageStats> stats, + Map<ComponentName, ResolverTarget> targetsDict, + List<ResolverTarget> targets, + Collator collator, + IResolverRankerService ranker, + ComponentName rankerServiceName, + boolean annotationsUsed, + PackageManager pm) { + mStats = stats; + mTargetsDict = targetsDict; + mTargets = targets; + mCollator = collator; + mRanker = ranker; + mRankerServiceName = rankerServiceName; + mAnnotationsUsed = annotationsUsed; + mPm = pm; + } + + @Override + public Comparator<ResolveInfo> getComparator() { + // TODO: doCompute() doesn't seem to be concerned about null-checking mStats. Is that + // a bug there, or do we have a way of knowing it will be non-null under certain + // conditions? + return (lhs, rhs) -> { + if (mStats != null) { + final ResolverTarget lhsTarget = mTargetsDict.get(new ComponentName( + lhs.activityInfo.packageName, lhs.activityInfo.name)); + final ResolverTarget rhsTarget = mTargetsDict.get(new ComponentName( + rhs.activityInfo.packageName, rhs.activityInfo.name)); + + if (lhsTarget != null && rhsTarget != null) { + final int selectProbabilityDiff = Float.compare( + rhsTarget.getSelectProbability(), lhsTarget.getSelectProbability()); + + if (selectProbabilityDiff != 0) { + return selectProbabilityDiff > 0 ? 1 : -1; + } + } + } + + CharSequence sa = lhs.loadLabel(mPm); + if (sa == null) sa = lhs.activityInfo.name; + CharSequence sb = rhs.loadLabel(mPm); + if (sb == null) sb = rhs.activityInfo.name; + + return mCollator.compare(sa.toString().trim(), sb.toString().trim()); + }; + } + + @Override + public float getScore(ComponentName name) { + final ResolverTarget target = mTargetsDict.get(name); + if (target != null) { + return target.getSelectProbability(); + } + return 0; + } + + @Override + public void notifyOnTargetSelected(ComponentName componentName) { + if (mRanker != null) { + try { + int selectedPos = new ArrayList<ComponentName>(mTargetsDict.keySet()) + .indexOf(componentName); + if (selectedPos >= 0 && mTargets != null) { + final float selectedProbability = getScore(componentName); + int order = 0; + for (ResolverTarget target : mTargets) { + if (target.getSelectProbability() > selectedProbability) { + order++; + } + } + logMetrics(order); + mRanker.train(mTargets, selectedPos); + } else { + if (DEBUG) { + Log.d(TAG, "Selected a unknown component: " + componentName); + } + } + } catch (RemoteException e) { + Log.e(TAG, "Error in Train: " + e); + } + } else { + if (DEBUG) { + Log.d(TAG, "Ranker is null; skip updateModel."); + } + } + } + + /** Records metrics for evaluation. */ + private void logMetrics(int selectedPos) { + if (mRankerServiceName != null) { + MetricsLogger metricsLogger = new MetricsLogger(); + LogMaker log = new LogMaker(MetricsEvent.ACTION_TARGET_SELECTED); + log.setComponentName(mRankerServiceName); + log.addTaggedData(MetricsEvent.FIELD_IS_CATEGORY_USED, mAnnotationsUsed); + log.addTaggedData(MetricsEvent.FIELD_RANKED_POSITION, selectedPos); + metricsLogger.write(log); + } + } + } } diff --git a/core/java/com/android/internal/compat/IPlatformCompat.aidl b/core/java/com/android/internal/compat/IPlatformCompat.aidl index 8847a490e39c..554155865080 100644 --- a/core/java/com/android/internal/compat/IPlatformCompat.aidl +++ b/core/java/com/android/internal/compat/IPlatformCompat.aidl @@ -47,6 +47,7 @@ interface IPlatformCompat { * @param appInfo representing the affected app * @throws SecurityException if logging is not allowed */ + @EnforcePermission("LOG_COMPAT_CHANGE") void reportChange(long changeId, in ApplicationInfo appInfo); /** @@ -60,6 +61,7 @@ interface IPlatformCompat { * @param packageName the package name of the app in question * @throws SecurityException if logging is not allowed */ + @EnforcePermission("LOG_COMPAT_CHANGE") void reportChangeByPackageName(long changeId, in String packageName, int userId); /** @@ -72,6 +74,7 @@ interface IPlatformCompat { * @param uid the UID of the app in question * @throws SecurityException if logging is not allowed */ + @EnforcePermission("LOG_COMPAT_CHANGE") void reportChangeByUid(long changeId, int uid); /** @@ -90,6 +93,7 @@ interface IPlatformCompat { * @return {@code true} if the change is enabled for the current app * @throws SecurityException if logging or reading compat confis is not allowed */ + @EnforcePermission(allOf={"LOG_COMPAT_CHANGE", "READ_COMPAT_CHANGE_CONFIG"}) boolean isChangeEnabled(long changeId, in ApplicationInfo appInfo); /** @@ -115,6 +119,7 @@ interface IPlatformCompat { * @return {@code true} if the change is enabled for the current app * @throws SecurityException if logging or reading compat confis is not allowed */ + @EnforcePermission(allOf={"LOG_COMPAT_CHANGE", "READ_COMPAT_CHANGE_CONFIG"}) boolean isChangeEnabledByPackageName(long changeId, in String packageName, int userId); /** @@ -140,6 +145,7 @@ interface IPlatformCompat { * @return {@code true} if the change is enabled for the current app * @throws SecurityException if logging or reading compat confis is not allowed */ + @EnforcePermission(allOf={"LOG_COMPAT_CHANGE", "READ_COMPAT_CHANGE_CONFIG"}) boolean isChangeEnabledByUid(long changeId, int uid); /** @@ -151,6 +157,7 @@ interface IPlatformCompat { * @param packageName the package name of the app whose changes will be overridden * @throws SecurityException if overriding changes is not permitted */ + @EnforcePermission("OVERRIDE_COMPAT_CHANGE_CONFIG") void setOverrides(in CompatibilityChangeConfig overrides, in String packageName); /** @@ -171,6 +178,7 @@ interface IPlatformCompat { * on specific apps by their package name * @throws SecurityException if overriding changes is not permitted */ + @EnforcePermission("OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD") void putAllOverridesOnReleaseBuilds(in CompatibilityOverridesByPackageConfig overridesByPackage); /** @@ -190,6 +198,7 @@ interface IPlatformCompat { * @param packageName the package name of the app whose changes will be overridden * @throws SecurityException if overriding changes is not permitted */ + @EnforcePermission("OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD") void putOverridesOnReleaseBuilds(in CompatibilityOverrideConfig overrides, in String packageName); /** @@ -201,6 +210,7 @@ interface IPlatformCompat { * @param packageName the package name of the app whose changes will be overridden * @throws SecurityException if overriding changes is not permitted. */ + @EnforcePermission("OVERRIDE_COMPAT_CHANGE_CONFIG") void setOverridesForTest(in CompatibilityChangeConfig overrides, in String packageName); /** @@ -213,6 +223,7 @@ interface IPlatformCompat { * @return {@code true} if an override existed * @throws SecurityException if overriding changes is not permitted */ + @EnforcePermission("OVERRIDE_COMPAT_CHANGE_CONFIG") boolean clearOverride(long changeId, String packageName); /** @@ -225,6 +236,7 @@ interface IPlatformCompat { * @return {@code true} if an override existed * @throws SecurityException if overriding changes is not permitted */ + @EnforcePermission("OVERRIDE_COMPAT_CHANGE_CONFIG") boolean clearOverrideForTest(long changeId, String packageName); /** @@ -245,6 +257,7 @@ interface IPlatformCompat { * removed for specific apps by their package name * @throws SecurityException if overriding changes is not permitted */ + @EnforcePermission("OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD") void removeAllOverridesOnReleaseBuilds(in CompatibilityOverridesToRemoveByPackageConfig overridesToRemoveByPackage); /** @@ -266,6 +279,7 @@ interface IPlatformCompat { * default behaviour * @throws SecurityException if overriding changes is not permitted */ + @EnforcePermission("OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD") void removeOverridesOnReleaseBuilds(in CompatibilityOverridesToRemoveConfig overridesToRemove, in String packageName); /** @@ -280,6 +294,7 @@ interface IPlatformCompat { * @return The number of changes that were enabled. * @throws SecurityException if overriding changes is not permitted. */ + @EnforcePermission("OVERRIDE_COMPAT_CHANGE_CONFIG") int enableTargetSdkChanges(in String packageName, int targetSdkVersion); /** @@ -294,6 +309,7 @@ interface IPlatformCompat { * @return the number of changes that were disabled * @throws SecurityException if overriding changes is not permitted. */ + @EnforcePermission("OVERRIDE_COMPAT_CHANGE_CONFIG") int disableTargetSdkChanges(in String packageName, int targetSdkVersion); /** @@ -304,6 +320,7 @@ interface IPlatformCompat { * @param packageName the package name of the app whose overrides will be cleared * @throws SecurityException if overriding changes is not permitted */ + @EnforcePermission("OVERRIDE_COMPAT_CHANGE_CONFIG") void clearOverrides(in String packageName); /** @@ -314,6 +331,7 @@ interface IPlatformCompat { * @param packageName the package name of the app whose overrides will be cleared * @throws SecurityException if overriding changes is not permitted */ + @EnforcePermission("OVERRIDE_COMPAT_CHANGE_CONFIG") void clearOverridesForTest(in String packageName); /** @@ -323,6 +341,7 @@ interface IPlatformCompat { * @return a {@link CompatibilityChangeConfig}, representing whether a change is enabled for * the given app or not */ + @EnforcePermission(allOf={"LOG_COMPAT_CHANGE", "READ_COMPAT_CHANGE_CONFIG"}) CompatibilityChangeConfig getAppConfig(in ApplicationInfo appInfo); /** @@ -330,6 +349,7 @@ interface IPlatformCompat { * * @return an array of {@link CompatibilityChangeInfo} known to the service */ + @EnforcePermission("READ_COMPAT_CHANGE_CONFIG") CompatibilityChangeInfo[] listAllChanges(); /** @@ -338,10 +358,12 @@ interface IPlatformCompat { * * @return an array of {@link CompatibilityChangeInfo} */ + @RequiresNoPermission CompatibilityChangeInfo[] listUIChanges(); /** * Gets an instance that can determine whether a changeid can be overridden for a package name. */ + @RequiresNoPermission IOverrideValidator getOverrideValidator(); } diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java index c94438e3cee8..ffb37529dd6e 100644 --- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java +++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java @@ -520,6 +520,13 @@ public final class SystemUiDeviceConfigFlags { public static final String USE_UNBUNDLED_SHARESHEET = "use_unbundled_sharesheet"; /** + * (int) The delay (in ms) before refreshing the Sharesheet UI after a change to the share + * target data model. For more info see go/sharesheet-list-view-update-delay. + */ + public static final String SHARESHEET_LIST_VIEW_UPDATE_DELAY = + "sharesheet_list_view_update_delay"; + + /** * (string) Name of the default QR code scanner activity. On the eligible devices this activity * is provided by GMS core. */ diff --git a/core/java/com/android/internal/content/FileSystemProvider.java b/core/java/com/android/internal/content/FileSystemProvider.java index a60b31078a86..73a4f1c4a154 100644 --- a/core/java/com/android/internal/content/FileSystemProvider.java +++ b/core/java/com/android/internal/content/FileSystemProvider.java @@ -62,7 +62,9 @@ import java.nio.file.FileVisitor; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Deque; import java.util.LinkedList; import java.util.List; import java.util.Locale; @@ -232,9 +234,9 @@ public abstract class FileSystemProvider extends DocumentsProvider { throw new FileNotFoundException(doc + " is not found under " + parent); } - LinkedList<String> path = new LinkedList<>(); + List<String> path = new ArrayList<>(); while (doc != null && FileUtils.contains(parent, doc)) { - path.addFirst(getDocIdForFile(doc)); + path.add(0, getDocIdForFile(doc)); doc = doc.getParentFile(); } @@ -448,10 +450,10 @@ public abstract class FileSystemProvider extends DocumentsProvider { File folder, String[] projection, Set<String> exclusion, Bundle queryArgs) throws FileNotFoundException { final MatrixCursor result = new MatrixCursor(resolveProjection(projection)); - final LinkedList<File> pending = new LinkedList<>(); + final List<File> pending = new ArrayList<>(); pending.add(folder); while (!pending.isEmpty() && result.getCount() < 24) { - final File file = pending.removeFirst(); + final File file = pending.remove(0); if (shouldHide(file)) continue; if (file.isDirectory()) { diff --git a/core/java/com/android/internal/content/om/OverlayConfig.java b/core/java/com/android/internal/content/om/OverlayConfig.java index b786526ce676..828e5cf1fd4c 100644 --- a/core/java/com/android/internal/content/om/OverlayConfig.java +++ b/core/java/com/android/internal/content/om/OverlayConfig.java @@ -183,7 +183,7 @@ public class OverlayConfig { final ParsedOverlayInfo p = partitionOverlayInfos.get(j); if (p.isStatic) { partitionConfigs.add(new ParsedConfiguration(p.packageName, - true /* enabled */, false /* mutable */, partition.policy, p)); + true /* enabled */, false /* mutable */, partition.policy, p, null)); } } diff --git a/core/java/com/android/internal/content/om/OverlayConfigParser.java b/core/java/com/android/internal/content/om/OverlayConfigParser.java index 0ab7b3d2ef86..5ab77d8d3236 100644 --- a/core/java/com/android/internal/content/om/OverlayConfigParser.java +++ b/core/java/com/android/internal/content/om/OverlayConfigParser.java @@ -22,6 +22,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.content.pm.PackagePartitions; import android.content.pm.PackagePartitions.SystemPartition; +import android.os.Build; import android.os.FileUtils; import android.util.ArraySet; import android.util.Log; @@ -56,6 +57,34 @@ import java.util.Map; **/ final class OverlayConfigParser { + /** Represents a part of a parsed overlay configuration XML file. */ + public static class ParsedConfigFile { + @NonNull public final String path; + @NonNull public final int line; + @Nullable public final String xml; + + ParsedConfigFile(@NonNull String path, int line, @Nullable String xml) { + this.path = path; + this.line = line; + this.xml = xml; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(getClass().getSimpleName()); + sb.append("{path="); + sb.append(path); + sb.append(", line="); + sb.append(line); + if (xml != null) { + sb.append(", xml="); + sb.append(xml); + } + sb.append("}"); + return sb.toString(); + } + } + // Default values for overlay configurations. static final boolean DEFAULT_ENABLED_STATE = false; static final boolean DEFAULT_MUTABILITY = true; @@ -94,24 +123,40 @@ final class OverlayConfigParser { @NonNull public final String policy; - /** Information extracted from the manifest of the overlay. */ - @NonNull + /** + * Information extracted from the manifest of the overlay. + * Null if the information was read from a config file instead of a manifest. + * + * @see parsedConfigFile + **/ + @Nullable public final ParsedOverlayInfo parsedInfo; + /** + * The config file used to configure this overlay. + * Null if no config file was used, in which case the overlay's manifest was used instead. + * + * @see parsedInfo + **/ + @Nullable + public final ParsedConfigFile parsedConfigFile; + ParsedConfiguration(@NonNull String packageName, boolean enabled, boolean mutable, - @NonNull String policy, @NonNull ParsedOverlayInfo parsedInfo) { + @NonNull String policy, @Nullable ParsedOverlayInfo parsedInfo, + @Nullable ParsedConfigFile parsedConfigFile) { this.packageName = packageName; this.enabled = enabled; this.mutable = mutable; this.policy = policy; this.parsedInfo = parsedInfo; + this.parsedConfigFile = parsedConfigFile; } @Override public String toString() { return getClass().getSimpleName() + String.format("{packageName=%s, enabled=%s" - + ", mutable=%s, policy=%s, parsedInfo=%s}", packageName, enabled, - mutable, policy, parsedInfo); + + ", mutable=%s, policy=%s, parsedInfo=%s, parsedConfigFile=%s}", + packageName, enabled, mutable, policy, parsedInfo, parsedConfigFile); } } @@ -417,9 +462,26 @@ final class OverlayConfigParser { Log.w(TAG, "found default-disabled immutable overlay " + packageName); } - final ParsedConfiguration Config = new ParsedConfiguration(packageName, isEnabled, - isMutable, parsingContext.mPartition.policy, info); + final ParsedConfigFile parsedConfigFile = new ParsedConfigFile( + configFile.getPath().intern(), parser.getLineNumber(), + (Build.IS_ENG || Build.IS_USERDEBUG) ? currentParserContextToString(parser) : null); + final ParsedConfiguration config = new ParsedConfiguration(packageName, isEnabled, + isMutable, parsingContext.mPartition.policy, info, parsedConfigFile); parsingContext.mConfiguredOverlays.add(packageName); - parsingContext.mOrderedConfigurations.add(Config); + parsingContext.mOrderedConfigurations.add(config); + } + + private static String currentParserContextToString(@NonNull XmlPullParser parser) { + StringBuilder sb = new StringBuilder("<"); + sb.append(parser.getName()); + sb.append(" "); + for (int i = 0; i < parser.getAttributeCount(); i++) { + sb.append(parser.getAttributeName(i)); + sb.append("=\""); + sb.append(parser.getAttributeValue(i)); + sb.append("\" "); + } + sb.append("/>"); + return sb.toString(); } } diff --git a/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl b/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl index 2ee47b64b1a5..4babb7080176 100644 --- a/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl +++ b/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl @@ -34,7 +34,7 @@ oneway interface IInputMethodPrivilegedOperations { void setInputMethod(String id, in AndroidFuture future /* T=Void */); void setInputMethodAndSubtype(String id, in InputMethodSubtype subtype, in AndroidFuture future /* T=Void */); - void hideMySoftInput(int flags, in AndroidFuture future /* T=Void */); + void hideMySoftInput(int flags, int reason, in AndroidFuture future /* T=Void */); void showMySoftInput(int flags, in AndroidFuture future /* T=Void */); void updateStatusIconAsync(String packageName, int iconId); void switchToPreviousInputMethod(in AndroidFuture future /* T=Boolean */); diff --git a/core/java/com/android/internal/inputmethod/InputMethodDebug.java b/core/java/com/android/internal/inputmethod/InputMethodDebug.java index d6697684f79e..97ad0840fbd5 100644 --- a/core/java/com/android/internal/inputmethod/InputMethodDebug.java +++ b/core/java/com/android/internal/inputmethod/InputMethodDebug.java @@ -194,12 +194,12 @@ public final class InputMethodDebug { return "SHOW_SOFT_INPUT"; case SoftInputShowHideReason.ATTACH_NEW_INPUT: return "ATTACH_NEW_INPUT"; - case SoftInputShowHideReason.SHOW_MY_SOFT_INPUT: - return "SHOW_MY_SOFT_INPUT"; + case SoftInputShowHideReason.SHOW_SOFT_INPUT_FROM_IME: + return "SHOW_SOFT_INPUT_FROM_IME"; case SoftInputShowHideReason.HIDE_SOFT_INPUT: return "HIDE_SOFT_INPUT"; - case SoftInputShowHideReason.HIDE_MY_SOFT_INPUT: - return "HIDE_MY_SOFT_INPUT"; + case SoftInputShowHideReason.HIDE_SOFT_INPUT_FROM_IME: + return "HIDE_SOFT_INPUT_FROM_IME"; case SoftInputShowHideReason.SHOW_AUTO_EDITOR_FORWARD_NAV: return "SHOW_AUTO_EDITOR_FORWARD_NAV"; case SoftInputShowHideReason.SHOW_STATE_VISIBLE_FORWARD_NAV: @@ -242,6 +242,16 @@ public final class InputMethodDebug { return "SHOW_SOFT_INPUT_BY_INSETS_API"; case SoftInputShowHideReason.HIDE_DISPLAY_IME_POLICY_HIDE: return "HIDE_DISPLAY_IME_POLICY_HIDE"; + case SoftInputShowHideReason.HIDE_SOFT_INPUT_BY_INSETS_API: + return "HIDE_SOFT_INPUT_BY_INSETS_API"; + case SoftInputShowHideReason.HIDE_SOFT_INPUT_BY_BACK_KEY: + return "HIDE_SOFT_INPUT_BY_BACK_KEY"; + case SoftInputShowHideReason.HIDE_SOFT_INPUT_IME_TOGGLE_SOFT_INPUT: + return "HIDE_SOFT_INPUT_IME_TOGGLE_SOFT_INPUT"; + case SoftInputShowHideReason.HIDE_SOFT_INPUT_EXTRACT_INPUT_CHANGED: + return "HIDE_SOFT_INPUT_EXTRACT_INPUT_CHANGED"; + case SoftInputShowHideReason.HIDE_SOFT_INPUT_IMM_DEPRECATION: + return "HIDE_SOFT_INPUT_IMM_DEPRECATION"; default: return "Unknown=" + reason; } diff --git a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java index 15d7acfb6e0a..67c2103450bb 100644 --- a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java +++ b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java @@ -253,18 +253,19 @@ public final class InputMethodPrivilegedOperations { * Calls {@link IInputMethodPrivilegedOperations#hideMySoftInput(int, IVoidResultCallback)} * * @param flags additional operating flags + * @param reason the reason to hide soft input * @see android.view.inputmethod.InputMethodManager#HIDE_IMPLICIT_ONLY * @see android.view.inputmethod.InputMethodManager#HIDE_NOT_ALWAYS */ @AnyThread - public void hideMySoftInput(int flags) { + public void hideMySoftInput(int flags, @SoftInputShowHideReason int reason) { final IInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull(); if (ops == null) { return; } try { final AndroidFuture<Void> future = new AndroidFuture<>(); - ops.hideMySoftInput(flags, future); + ops.hideMySoftInput(flags, reason, future); CompletableFutureUtil.getResult(future); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); diff --git a/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java b/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java index 9e5776292031..97ad5cb4663c 100644 --- a/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java +++ b/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java @@ -19,8 +19,11 @@ package com.android.internal.inputmethod; import static java.lang.annotation.RetentionPolicy.SOURCE; import android.annotation.IntDef; +import android.os.IBinder; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; import java.lang.annotation.Retention; @@ -31,9 +34,9 @@ import java.lang.annotation.Retention; @IntDef(value = { SoftInputShowHideReason.SHOW_SOFT_INPUT, SoftInputShowHideReason.ATTACH_NEW_INPUT, - SoftInputShowHideReason.SHOW_MY_SOFT_INPUT, + SoftInputShowHideReason.SHOW_SOFT_INPUT_FROM_IME, SoftInputShowHideReason.HIDE_SOFT_INPUT, - SoftInputShowHideReason.HIDE_MY_SOFT_INPUT, + SoftInputShowHideReason.HIDE_SOFT_INPUT_FROM_IME, SoftInputShowHideReason.SHOW_AUTO_EDITOR_FORWARD_NAV, SoftInputShowHideReason.SHOW_STATE_VISIBLE_FORWARD_NAV, SoftInputShowHideReason.SHOW_STATE_ALWAYS_VISIBLE, @@ -55,7 +58,12 @@ import java.lang.annotation.Retention; SoftInputShowHideReason.SHOW_TOGGLE_SOFT_INPUT, SoftInputShowHideReason.HIDE_TOGGLE_SOFT_INPUT, SoftInputShowHideReason.SHOW_SOFT_INPUT_BY_INSETS_API, - SoftInputShowHideReason.HIDE_DISPLAY_IME_POLICY_HIDE}) + SoftInputShowHideReason.HIDE_DISPLAY_IME_POLICY_HIDE, + SoftInputShowHideReason.HIDE_SOFT_INPUT_BY_INSETS_API, + SoftInputShowHideReason.HIDE_SOFT_INPUT_BY_BACK_KEY, + SoftInputShowHideReason.HIDE_SOFT_INPUT_IME_TOGGLE_SOFT_INPUT, + SoftInputShowHideReason.HIDE_SOFT_INPUT_EXTRACT_INPUT_CHANGED, + SoftInputShowHideReason.HIDE_SOFT_INPUT_IMM_DEPRECATION}) public @interface SoftInputShowHideReason { /** Show soft input by {@link android.view.inputmethod.InputMethodManager#showSoftInput}. */ int SHOW_SOFT_INPUT = 0; @@ -63,8 +71,12 @@ public @interface SoftInputShowHideReason { /** Show soft input when {@code InputMethodManagerService#attachNewInputLocked} called. */ int ATTACH_NEW_INPUT = 1; - /** Show soft input by {@code InputMethodManagerService#showMySoftInput}. */ - int SHOW_MY_SOFT_INPUT = 2; + /** Show soft input by {@code InputMethodManagerService#showMySoftInput}. This is triggered when + * the IME process try to show the keyboard. + * + * @see android.inputmethodservice.InputMethodService#requestShowSelf(int) + */ + int SHOW_SOFT_INPUT_FROM_IME = 2; /** * Hide soft input by @@ -72,8 +84,11 @@ public @interface SoftInputShowHideReason { */ int HIDE_SOFT_INPUT = 3; - /** Hide soft input by {@code InputMethodManagerService#hideMySoftInput}. */ - int HIDE_MY_SOFT_INPUT = 4; + /** + * Hide soft input by + * {@link android.inputmethodservice.InputMethodService#requestHideSelf(int)}. + */ + int HIDE_SOFT_INPUT_FROM_IME = 4; /** * Show soft input when navigated forward to the window (with @@ -203,4 +218,32 @@ public @interface SoftInputShowHideReason { * See also {@code InputMethodManagerService#mImeHiddenByDisplayPolicy}. */ int HIDE_DISPLAY_IME_POLICY_HIDE = 26; + + /** + * Hide soft input by {@link android.view.InsetsController#hide(int)}. + */ + int HIDE_SOFT_INPUT_BY_INSETS_API = 27; + + /** + * Hide soft input by {@link android.inputmethodservice.InputMethodService#handleBack(boolean)}. + */ + int HIDE_SOFT_INPUT_BY_BACK_KEY = 28; + + /** + * Hide soft input by + * {@link android.inputmethodservice.InputMethodService#onToggleSoftInput(int, int)}. + */ + int HIDE_SOFT_INPUT_IME_TOGGLE_SOFT_INPUT = 29; + + /** + * Hide soft input by + * {@link android.inputmethodservice.InputMethodService#onExtractingInputChanged(EditorInfo)})}. + */ + int HIDE_SOFT_INPUT_EXTRACT_INPUT_CHANGED = 30; + + /** + * Hide soft input by the deprecated + * {@link InputMethodManager#hideSoftInputFromInputMethod(IBinder, int)}. + */ + int HIDE_SOFT_INPUT_IMM_DEPRECATION = 31; } diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java index 488fb180723e..12571b1ef521 100644 --- a/core/java/com/android/internal/policy/PhoneWindow.java +++ b/core/java/com/android/internal/policy/PhoneWindow.java @@ -912,6 +912,12 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } } + if (!st.hasPanelItems()) { + // Ensure that |st.decorView| has its actual content. Otherwise, an empty window can be + // created and cause ANR. + return; + } + st.isHandled = false; WindowManager.LayoutParams lp = new WindowManager.LayoutParams( diff --git a/core/java/com/android/internal/view/menu/CascadingMenuPopup.java b/core/java/com/android/internal/view/menu/CascadingMenuPopup.java index bf3e8d56b6bc..a0f7905771a2 100644 --- a/core/java/com/android/internal/view/menu/CascadingMenuPopup.java +++ b/core/java/com/android/internal/view/menu/CascadingMenuPopup.java @@ -1,11 +1,5 @@ package com.android.internal.view.menu; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; - import android.annotation.AttrRes; import android.annotation.IntDef; import android.annotation.NonNull; @@ -22,16 +16,16 @@ import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; -import android.view.ViewTreeObserver; import android.view.View.OnAttachStateChangeListener; import android.view.View.OnKeyListener; +import android.view.ViewTreeObserver; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.widget.AbsListView; import android.widget.FrameLayout; import android.widget.HeaderViewListAdapter; import android.widget.ListAdapter; -import android.widget.MenuItemHoverListener; import android.widget.ListView; +import android.widget.MenuItemHoverListener; import android.widget.MenuPopupWindow; import android.widget.PopupWindow; import android.widget.PopupWindow.OnDismissListener; @@ -40,6 +34,11 @@ import android.widget.TextView; import com.android.internal.R; import com.android.internal.util.Preconditions; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; +import java.util.List; + /** * A popup for a menu which will allow multiple submenus to appear in a cascading fashion, side by * side. @@ -70,7 +69,7 @@ final class CascadingMenuPopup extends MenuPopup implements MenuPresenter, OnKey private final Handler mSubMenuHoverHandler; /** List of menus that were added before this popup was shown. */ - private final List<MenuBuilder> mPendingMenus = new LinkedList<>(); + private final List<MenuBuilder> mPendingMenus = new ArrayList<>(); /** * List of open menus. The first item is the root menu and each diff --git a/core/java/com/android/internal/widget/ConversationHeaderLinearLayout.java b/core/java/com/android/internal/widget/ConversationHeaderLinearLayout.java index 481183e700a2..c1e2840f0a8b 100644 --- a/core/java/com/android/internal/widget/ConversationHeaderLinearLayout.java +++ b/core/java/com/android/internal/widget/ConversationHeaderLinearLayout.java @@ -23,6 +23,7 @@ import android.view.View; import android.widget.LinearLayout; import android.widget.RemoteViews; +import java.util.ArrayList; import java.util.LinkedList; import java.util.List; @@ -96,7 +97,7 @@ public class ConversationHeaderLinearLayout extends LinearLayout { continue; } if (visibleChildrenToShorten == null) { - visibleChildrenToShorten = new LinkedList<>(); + visibleChildrenToShorten = new ArrayList<>(count); } visibleChildrenToShorten.add(new ViewInfo(child)); remainingWeight += Math.max(0, weight); diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index a94b30707604..6771cdf84717 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -39,7 +39,6 @@ import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.os.Build; import android.os.Handler; -import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.RemoteException; @@ -47,7 +46,6 @@ import android.os.ServiceManager; import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; -import android.os.storage.IStorageManager; import android.os.storage.StorageManager; import android.provider.Settings; import android.text.TextUtils; diff --git a/core/java/com/android/internal/widget/floatingtoolbar/LocalFloatingToolbarPopup.java b/core/java/com/android/internal/widget/floatingtoolbar/LocalFloatingToolbarPopup.java index 8c61a12b47e6..95a4e1238e06 100644 --- a/core/java/com/android/internal/widget/floatingtoolbar/LocalFloatingToolbarPopup.java +++ b/core/java/com/android/internal/widget/floatingtoolbar/LocalFloatingToolbarPopup.java @@ -61,10 +61,10 @@ import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; +import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.LinkedHashMap; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Objects; @@ -950,9 +950,9 @@ public final class LocalFloatingToolbarPopup implements FloatingToolbarPopup { int availableWidth = toolbarWidth; - final LinkedList<MenuItem> remainingMenuItems = new LinkedList<>(); + final ArrayList<MenuItem> remainingMenuItems = new ArrayList<>(); // add the overflow menu items to the end of the remainingMenuItems list. - final LinkedList<MenuItem> overflowMenuItems = new LinkedList(); + final ArrayList<MenuItem> overflowMenuItems = new ArrayList<>(); for (MenuItem menuItem : menuItems) { if (menuItem.getItemId() != android.R.id.textAssist && menuItem.requiresOverflow()) { @@ -969,7 +969,7 @@ public final class LocalFloatingToolbarPopup implements FloatingToolbarPopup { int lastGroupId = -1; boolean isFirstItem = true; while (!remainingMenuItems.isEmpty()) { - final MenuItem menuItem = remainingMenuItems.peek(); + final MenuItem menuItem = remainingMenuItems.get(0); // if this is the first item, regardless of requiresOverflow(), it should be // displayed on the main panel. Otherwise all items including this one will be @@ -1022,7 +1022,7 @@ public final class LocalFloatingToolbarPopup implements FloatingToolbarPopup { params.width = menuItemButtonWidth; menuItemButton.setLayoutParams(params); availableWidth -= menuItemButtonWidth; - remainingMenuItems.pop(); + remainingMenuItems.remove(0); } else { break; } diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index eba6cca76389..817b3154889b 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -676,7 +676,6 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool p char dex2oatFlagsBuf[PROPERTY_VALUE_MAX]; char dex2oatImageFlagsBuf[PROPERTY_VALUE_MAX]; char extraOptsBuf[PROPERTY_VALUE_MAX]; - char voldDecryptBuf[PROPERTY_VALUE_MAX]; char perfettoHprofOptBuf[sizeof("-XX:PerfettoHprof=") + PROPERTY_VALUE_MAX]; char perfettoJavaHeapStackOptBuf[ sizeof("-XX:PerfettoJavaHeapStackProf=") + PROPERTY_VALUE_MAX]; @@ -958,19 +957,9 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool p addOption("-Xint:jit"); } - // If we are booting without the real /data, don't spend time compiling. - property_get("vold.decrypt", voldDecryptBuf, ""); - bool skip_compilation = ((strcmp(voldDecryptBuf, "trigger_restart_min_framework") == 0) || - (strcmp(voldDecryptBuf, "1") == 0)); - // Extra options for JIT. - if (skip_compilation) { - addOption("-Xcompiler-option"); - addOption("--compiler-filter=assume-verified"); - } else { - parseCompilerOption("dalvik.vm.dex2oat-filter", dex2oatCompilerFilterBuf, - "--compiler-filter=", "-Xcompiler-option"); - } + parseCompilerOption("dalvik.vm.dex2oat-filter", dex2oatCompilerFilterBuf, + "--compiler-filter=", "-Xcompiler-option"); parseCompilerOption("dalvik.vm.dex2oat-threads", dex2oatThreadsBuf, "-j", "-Xcompiler-option"); parseCompilerOption("dalvik.vm.dex2oat-cpu-set", dex2oatCpuSetBuf, "--cpu-set=", "-Xcompiler-option"); @@ -1011,52 +1000,48 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool p parseExtraOpts(extraOptsBuf, NULL); // Extra options for boot image generation. - if (skip_compilation) { - addOption("-Xnoimage-dex2oat"); - } else { - parseCompilerRuntimeOption("dalvik.vm.image-dex2oat-Xms", dex2oatXmsImageFlagsBuf, - "-Xms", "-Ximage-compiler-option"); - parseCompilerRuntimeOption("dalvik.vm.image-dex2oat-Xmx", dex2oatXmxImageFlagsBuf, - "-Xmx", "-Ximage-compiler-option"); - - parseCompilerOption("dalvik.vm.image-dex2oat-filter", dex2oatImageCompilerFilterBuf, - "--compiler-filter=", "-Ximage-compiler-option"); - - // If there is a dirty-image-objects file, push it. - if (hasFile("/system/etc/dirty-image-objects")) { - addOption("-Ximage-compiler-option"); - addOption("--dirty-image-objects=/system/etc/dirty-image-objects"); - } + parseCompilerRuntimeOption("dalvik.vm.image-dex2oat-Xms", dex2oatXmsImageFlagsBuf, + "-Xms", "-Ximage-compiler-option"); + parseCompilerRuntimeOption("dalvik.vm.image-dex2oat-Xmx", dex2oatXmxImageFlagsBuf, + "-Xmx", "-Ximage-compiler-option"); + + parseCompilerOption("dalvik.vm.image-dex2oat-filter", dex2oatImageCompilerFilterBuf, + "--compiler-filter=", "-Ximage-compiler-option"); + + // If there is a dirty-image-objects file, push it. + if (hasFile("/system/etc/dirty-image-objects")) { + addOption("-Ximage-compiler-option"); + addOption("--dirty-image-objects=/system/etc/dirty-image-objects"); + } - parseCompilerOption("dalvik.vm.image-dex2oat-threads", dex2oatThreadsImageBuf, "-j", - "-Ximage-compiler-option"); - parseCompilerOption("dalvik.vm.image-dex2oat-cpu-set", dex2oatCpuSetImageBuf, "--cpu-set=", - "-Ximage-compiler-option"); - - // The runtime may compile a boot image, when necessary, not using installd. Thus, we need - // to pass the instruction-set-features/variant as an image-compiler-option. - // Note: it is OK to reuse the buffer, as the values are exactly the same between - // * compiler-option, used for runtime compilation (DexClassLoader) - // * image-compiler-option, used for boot-image compilation on device - parseCompilerOption(dex2oat_isa_variant_key, dex2oat_isa_variant, - "--instruction-set-variant=", "-Ximage-compiler-option"); - parseCompilerOption(dex2oat_isa_features_key, dex2oat_isa_features, - "--instruction-set-features=", "-Ximage-compiler-option"); - - if (generate_debug_info) { - addOption("-Ximage-compiler-option"); - addOption("--generate-debug-info"); - } + parseCompilerOption("dalvik.vm.image-dex2oat-threads", dex2oatThreadsImageBuf, "-j", + "-Ximage-compiler-option"); + parseCompilerOption("dalvik.vm.image-dex2oat-cpu-set", dex2oatCpuSetImageBuf, "--cpu-set=", + "-Ximage-compiler-option"); - if (generate_mini_debug_info) { - addOption("-Ximage-compiler-option"); - addOption("--generate-mini-debug-info"); - } + // The runtime may compile a boot image, when necessary, not using installd. Thus, we need + // to pass the instruction-set-features/variant as an image-compiler-option. + // Note: it is OK to reuse the buffer, as the values are exactly the same between + // * compiler-option, used for runtime compilation (DexClassLoader) + // * image-compiler-option, used for boot-image compilation on device + parseCompilerOption(dex2oat_isa_variant_key, dex2oat_isa_variant, + "--instruction-set-variant=", "-Ximage-compiler-option"); + parseCompilerOption(dex2oat_isa_features_key, dex2oat_isa_features, + "--instruction-set-features=", "-Ximage-compiler-option"); - property_get("dalvik.vm.image-dex2oat-flags", dex2oatImageFlagsBuf, ""); - parseExtraOpts(dex2oatImageFlagsBuf, "-Ximage-compiler-option"); + if (generate_debug_info) { + addOption("-Ximage-compiler-option"); + addOption("--generate-debug-info"); } + if (generate_mini_debug_info) { + addOption("-Ximage-compiler-option"); + addOption("--generate-mini-debug-info"); + } + + property_get("dalvik.vm.image-dex2oat-flags", dex2oatImageFlagsBuf, ""); + parseExtraOpts(dex2oatImageFlagsBuf, "-Ximage-compiler-option"); + /* Set the properties for locale */ { strcpy(localeOption, "-Duser.locale="); diff --git a/core/jni/android_view_DisplayEventReceiver.cpp b/core/jni/android_view_DisplayEventReceiver.cpp index 05855867ed62..c9110d144018 100644 --- a/core/jni/android_view_DisplayEventReceiver.cpp +++ b/core/jni/android_view_DisplayEventReceiver.cpp @@ -90,8 +90,9 @@ NativeDisplayEventReceiver::NativeDisplayEventReceiver(JNIEnv* env, jobject rece const sp<MessageQueue>& messageQueue, jint vsyncSource, jint eventRegistration) : DisplayEventDispatcher(messageQueue->getLooper(), - static_cast<ISurfaceComposer::VsyncSource>(vsyncSource), - static_cast<ISurfaceComposer::EventRegistration>(eventRegistration)), + static_cast<gui::ISurfaceComposer::VsyncSource>(vsyncSource), + static_cast<gui::ISurfaceComposer::EventRegistration>( + eventRegistration)), mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)), mMessageQueue(messageQueue) { ALOGV("receiver %p ~ Initializing display event receiver.", this); diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 51a708b76801..77a26030292d 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -1957,8 +1957,10 @@ static void nativeSetFrameTimelineVsync(JNIEnv* env, jclass clazz, jlong transac jlong frameTimelineVsyncId) { auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj); - transaction->setFrameTimelineInfo( - {frameTimelineVsyncId, android::os::IInputConstants::INVALID_INPUT_EVENT_ID}); + FrameTimelineInfo ftInfo; + ftInfo.vsyncId = frameTimelineVsyncId; + ftInfo.inputEventId = android::os::IInputConstants::INVALID_INPUT_EVENT_ID; + transaction->setFrameTimelineInfo(ftInfo); } static void nativeAddTransactionCommittedListener(JNIEnv* env, jclass clazz, jlong transactionObj, @@ -2043,7 +2045,7 @@ static jlong nativeCreateJankDataListenerWrapper(JNIEnv* env, jclass clazz, } static jint nativeGetGPUContextPriority(JNIEnv* env, jclass clazz) { - return static_cast<jint>(SurfaceComposerClient::getGPUContextPriority()); + return static_cast<jint>(SurfaceComposerClient::getGpuContextPriority()); } static void nativeSetTransformHint(JNIEnv* env, jclass clazz, jlong nativeSurfaceControl, diff --git a/core/proto/OWNERS b/core/proto/OWNERS index a4463e4e96c5..907093343a3f 100644 --- a/core/proto/OWNERS +++ b/core/proto/OWNERS @@ -16,6 +16,7 @@ roosa@google.com per-file package_item_info.proto = toddke@google.com,patb@google.com per-file usagestatsservice.proto, usagestatsservice_v2.proto = file:/core/java/android/app/usage/OWNERS per-file apphibernationservice.proto = file:/core/java/android/apphibernation/OWNERS +per-file android/hardware/sensorprivacy.proto = ntmyren@google.com,evanseverson@google.com,ewol@google.com # Biometrics jaggies@google.com diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto index 7205dd817eb5..6ec71baa836a 100644 --- a/core/proto/android/server/activitymanagerservice.proto +++ b/core/proto/android/server/activitymanagerservice.proto @@ -91,6 +91,7 @@ message ReceiverListProto { repeated BroadcastFilterProto filters = 7; // Used to find this ReceiverList object in IntentResolver optional string hex_hash = 8; + optional int32 number_receivers = 9; } message ProcessRecordProto { diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 4075c5f4d8ae..ca71f0a3cce1 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -2278,7 +2278,8 @@ android:protectionLevel="signature|role" /> <!-- Allows bluetooth stack to access files - @hide This should only be used by Bluetooth apk. + This should only be granted to the Bluetooth apk. + @hide @SystemApi(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES) --> <permission android:name="android.permission.BLUETOOTH_STACK" android:protectionLevel="signature|role" /> @@ -4407,13 +4408,13 @@ <permission android:name="android.permission.TUNER_RESOURCE_ACCESS" android:protectionLevel="signature|privileged|vendorPrivileged" /> - <!-- This permission is required by Media Resource Manager Service when - accessing its overridePid Api. - <p>Protection level: signature + <!-- @SystemApi This permission is required by Media Resource Manager Service when + system services create MediaCodecs on behalf of other processes and apps. + <p>Protection level: signature|privileged|vendorPrivileged <p>Not for use by third-party applications. @hide --> <permission android:name="android.permission.MEDIA_RESOURCE_OVERRIDE_PID" - android:protectionLevel="signature" /> + android:protectionLevel="signature|privileged|vendorPrivileged" /> <uses-permission android:name="android.permission.MEDIA_RESOURCE_OVERRIDE_PID" /> <!-- This permission is required by Media Resource Observer Service when diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml index d1af2cd8b3aa..745733951f99 100644 --- a/core/res/res/values-fa/strings.xml +++ b/core/res/res/values-fa/strings.xml @@ -2274,11 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> ترجمه شد."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"پیام از <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> به <xliff:g id="TO_LANGUAGE">%2$s</xliff:g> ترجمه شد."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"فعالیت در پسزمینه"</string> - <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> - <skip /> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"برنامهای شارژ باتری را خالی میکند"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"یکی از برنامهها همچنان فعال است"</string> - <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> - <skip /> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> در پسزمینه درحال اجرا است. برای مدیریت مصرف باتری ضربه بزنید."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> ممکن است بر عمر باتری تأثیر بگذارد. برای مرور برنامههای فعال، ضربه بزنید."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"بررسی برنامههای فعال"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"نمیتوان از <xliff:g id="DEVICE">%1$s</xliff:g> شما به دوربین تلفن دسترسی داشت"</string> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index b23d8cab74d4..411a22d45728 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -3745,6 +3745,9 @@ "Guest" and "Reset guest". --> <bool name="config_guestUserAutoCreated">false</bool> + <!-- If true, owner can change guest user ephemeral state via UI option --> + <bool name="config_guestUserAllowEphemeralStateChange">true</bool> + <!-- Enforce strong auth on boot. Setting this to false represents a security risk and should not be ordinarily done. The only case in which this might be permissible is in a car head unit where there are hardware mechanisms to protect the device (physical keys) and not diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 21b235104694..d971add84278 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -394,6 +394,7 @@ <java-symbol type="bool" name="config_supportsInsecureLockScreen" /> <java-symbol type="bool" name="config_guestUserEphemeral" /> <java-symbol type="bool" name="config_guestUserAutoCreated" /> + <java-symbol type="bool" name="config_guestUserAllowEphemeralStateChange" /> <java-symbol type="bool" name="config_localDisplaysMirrorContent" /> <java-symbol type="array" name="config_localPrivateDisplayPorts" /> <java-symbol type="integer" name="config_defaultDisplayDefaultColorMode" /> diff --git a/core/tests/coretests/src/android/net/UriTest.java b/core/tests/coretests/src/android/net/UriTest.java index e083b0d460a2..3733bfa586d1 100644 --- a/core/tests/coretests/src/android/net/UriTest.java +++ b/core/tests/coretests/src/android/net/UriTest.java @@ -48,6 +48,7 @@ public class UriTest extends TestCase { public void testParcelling() { parcelAndUnparcel(Uri.parse("foo:bob%20lee")); parcelAndUnparcel(Uri.fromParts("foo", "bob lee", "fragment")); + parcelAndUnparcel(Uri.fromParts("https", "www.google.com", null)); parcelAndUnparcel(new Uri.Builder() .scheme("http") .authority("crazybob.org") @@ -890,9 +891,62 @@ public class UriTest extends TestCase { Throwable targetException = expected.getTargetException(); // Check that the exception was thrown for the correct reason. assertEquals("Unknown representation: 0", targetException.getMessage()); + } finally { + parcel.recycle(); } } + private Uri buildUriFromRawParcel(boolean argumentsEncoded, + String scheme, + String authority, + String path, + String query, + String fragment) { + // Representation value (from AbstractPart.REPRESENTATION_{ENCODED,DECODED}). + final int representation = argumentsEncoded ? 1 : 2; + Parcel parcel = Parcel.obtain(); + try { + parcel.writeInt(3); // hierarchical + parcel.writeString8(scheme); + parcel.writeInt(representation); + parcel.writeString8(authority); + parcel.writeInt(representation); + parcel.writeString8(path); + parcel.writeInt(representation); + parcel.writeString8(query); + parcel.writeInt(representation); + parcel.writeString8(fragment); + parcel.setDataPosition(0); + return Uri.CREATOR.createFromParcel(parcel); + } finally { + parcel.recycle(); + } + } + + public void testUnparcelMalformedPath() { + // Regression tests for b/171966843. + + // Test cases with arguments encoded (covering testing `scheme` * `authority` options). + Uri uri0 = buildUriFromRawParcel(true, "https", "google.com", "@evil.com", null, null); + assertEquals("https://google.com/@evil.com", uri0.toString()); + Uri uri1 = buildUriFromRawParcel(true, null, "google.com", "@evil.com", "name=spark", "x"); + assertEquals("//google.com/@evil.com?name=spark#x", uri1.toString()); + Uri uri2 = buildUriFromRawParcel(true, "http:", null, "@evil.com", null, null); + assertEquals("http::/@evil.com", uri2.toString()); + Uri uri3 = buildUriFromRawParcel(true, null, null, "@evil.com", null, null); + assertEquals("@evil.com", uri3.toString()); + + // Test cases with arguments not encoded (covering testing `scheme` * `authority` options). + Uri uriA = buildUriFromRawParcel(false, "https", "google.com", "@evil.com", null, null); + assertEquals("https://google.com/%40evil.com", uriA.toString()); + Uri uriB = buildUriFromRawParcel(false, null, "google.com", "@evil.com", null, null); + assertEquals("//google.com/%40evil.com", uriB.toString()); + Uri uriC = buildUriFromRawParcel(false, "http:", null, "@evil.com", null, null); + assertEquals("http::/%40evil.com", uriC.toString()); + Uri uriD = buildUriFromRawParcel(false, null, null, "@evil.com", "name=spark", "y"); + assertEquals("%40evil.com?name%3Dspark#y", uriD.toString()); + } + public void testToSafeString() { checkToSafeString("tel:xxxxxx", "tel:Google"); checkToSafeString("tel:xxxxxxxxxx", "tel:1234567890"); diff --git a/core/tests/coretests/src/android/text/StaticLayoutTest.java b/core/tests/coretests/src/android/text/StaticLayoutTest.java index 0ebf03fab966..925da4968517 100644 --- a/core/tests/coretests/src/android/text/StaticLayoutTest.java +++ b/core/tests/coretests/src/android/text/StaticLayoutTest.java @@ -24,6 +24,7 @@ import static org.junit.Assert.assertTrue; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Paint.FontMetricsInt; +import android.graphics.text.LineBreakConfig; import android.os.LocaleList; import android.platform.test.annotations.Presubmit; import android.text.Layout.Alignment; @@ -925,4 +926,24 @@ public class StaticLayoutTest { assertEquals(0, layout.getHeight(true)); assertEquals(2, layout.getLineCount()); } + + @Test + public void testBuilder_autoPhraseBreaking() { + { + // setAutoPhraseBreaking true + LineBreakConfig lineBreakConfig = new LineBreakConfig.Builder() + .setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_STYLE_NONE) + .setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE) + .setAutoPhraseBreaking(true) + .build(); + final String text = "これが正解。"; + // Obtain. + StaticLayout.Builder builder = StaticLayout.Builder.obtain(text, 0, + text.length(), mDefaultPaint, DEFAULT_OUTER_WIDTH); + builder.setLineBreakConfig(lineBreakConfig); + builder.build(); + assertEquals(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE, + builder.getLineBreakWordStyle()); + } + } } diff --git a/core/tests/coretests/src/android/view/stylus/HandwritingInitiatorTest.java b/core/tests/coretests/src/android/view/stylus/HandwritingInitiatorTest.java index e303934c4aad..b3b19ce7a285 100644 --- a/core/tests/coretests/src/android/view/stylus/HandwritingInitiatorTest.java +++ b/core/tests/coretests/src/android/view/stylus/HandwritingInitiatorTest.java @@ -34,6 +34,8 @@ import android.app.Instrumentation; import android.content.Context; import android.graphics.Rect; import android.platform.test.annotations.Presubmit; +import android.util.DisplayMetrics; +import android.util.TypedValue; import android.view.HandwritingInitiator; import android.view.InputDevice; import android.view.MotionEvent; @@ -61,23 +63,32 @@ import org.junit.runner.RunWith; public class HandwritingInitiatorTest { private static final int TOUCH_SLOP = 8; private static final long TIMEOUT = ViewConfiguration.getLongPressTimeout(); + private static final int HANDWRITING_AREA_PADDING_DIP = 20; + private static final Rect sHwArea = new Rect(100, 200, 500, 500); private HandwritingInitiator mHandwritingInitiator; private View mTestView; - private Context mContext; + private Context mContext; + private int mHandwritingAreaPaddingPx; @Before public void setup() { final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation(); mContext = mInstrumentation.getTargetContext(); - ViewConfiguration viewConfiguration = mock(ViewConfiguration.class); + final ViewConfiguration viewConfiguration = mock(ViewConfiguration.class); when(viewConfiguration.getScaledTouchSlop()).thenReturn(TOUCH_SLOP); + + final DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics(); InputMethodManager inputMethodManager = mContext.getSystemService(InputMethodManager.class); - mHandwritingInitiator = - spy(new HandwritingInitiator(viewConfiguration, inputMethodManager)); + mHandwritingInitiator = spy(new HandwritingInitiator(viewConfiguration, inputMethodManager, + displayMetrics)); + mHandwritingAreaPaddingPx = Math.round(TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, + HANDWRITING_AREA_PADDING_DIP, + displayMetrics)); mTestView = createView(sHwArea, true); mHandwritingInitiator.updateHandwritingAreasForView(mTestView); } @@ -127,6 +138,24 @@ public class HandwritingInitiatorTest { } @Test + public void onTouchEvent_startHandwriting_when_stylusMove_withinExtendedHWArea() { + mHandwritingInitiator.onInputConnectionCreated(mTestView); + final int x1 = sHwArea.left - mHandwritingAreaPaddingPx / 2; + final int y1 = sHwArea.top - mHandwritingAreaPaddingPx / 2; + MotionEvent stylusEvent1 = createStylusEvent(ACTION_DOWN, x1, y1, 0); + mHandwritingInitiator.onTouchEvent(stylusEvent1); + + final int x2 = x1 + TOUCH_SLOP * 2; + final int y2 = y1; + + MotionEvent stylusEvent2 = createStylusEvent(ACTION_MOVE, x2, y2, 0); + mHandwritingInitiator.onTouchEvent(stylusEvent2); + + // Stylus movement within extended HandwritingArea should trigger IMM.startHandwriting once. + verify(mHandwritingInitiator, times(1)).startHandwriting(mTestView); + } + + @Test public void onTouchEvent_startHandwriting_inputConnectionBuiltAfterStylusMove() { final int x1 = (sHwArea.left + sHwArea.right) / 2; final int y1 = (sHwArea.top + sHwArea.bottom) / 2; @@ -145,6 +174,24 @@ public class HandwritingInitiatorTest { } @Test + public void onTouchEvent_startHandwriting_inputConnectionBuilt_stylusMoveInExtendedHWArea() { + final int x1 = sHwArea.right + mHandwritingAreaPaddingPx / 2; + final int y1 = sHwArea.bottom + mHandwritingAreaPaddingPx / 2; + MotionEvent stylusEvent1 = createStylusEvent(ACTION_DOWN, x1, y1, 0); + mHandwritingInitiator.onTouchEvent(stylusEvent1); + + final int x2 = x1 + TOUCH_SLOP * 2; + final int y2 = y1; + MotionEvent stylusEvent2 = createStylusEvent(ACTION_MOVE, x2, y2, 0); + mHandwritingInitiator.onTouchEvent(stylusEvent2); + + // InputConnection is created after stylus movement. + mHandwritingInitiator.onInputConnectionCreated(mTestView); + + verify(mHandwritingInitiator, times(1)).startHandwriting(mTestView); + } + + @Test public void onTouchEvent_notStartHandwriting_when_stylusTap_withinHWArea() { mHandwritingInitiator.onInputConnectionCreated(mTestView); final int x1 = 200; @@ -213,6 +260,23 @@ public class HandwritingInitiatorTest { } @Test + public void onTouchEvent_focusView_stylusMoveOnce_withinExtendedHWArea() { + final int x1 = sHwArea.left - mHandwritingAreaPaddingPx / 2; + final int y1 = sHwArea.top - mHandwritingAreaPaddingPx / 2; + MotionEvent stylusEvent1 = createStylusEvent(ACTION_DOWN, x1, y1, 0); + mHandwritingInitiator.onTouchEvent(stylusEvent1); + + final int x2 = x1 + TOUCH_SLOP * 2; + final int y2 = y1; + + MotionEvent stylusEvent2 = createStylusEvent(ACTION_MOVE, x2, y2, 0); + mHandwritingInitiator.onTouchEvent(stylusEvent2); + + // HandwritingInitiator will request focus for the registered view. + verify(mTestView, times(1)).requestFocus(); + } + + @Test public void autoHandwriting_whenDisabled_wontStartHW() { View mockView = createView(sHwArea, false); mHandwritingInitiator.onInputConnectionCreated(mockView); diff --git a/core/tests/coretests/src/com/android/internal/app/AbstractResolverComparatorTest.java b/core/tests/coretests/src/com/android/internal/app/AbstractResolverComparatorTest.java index 04b888623732..3e640c1bad39 100644 --- a/core/tests/coretests/src/com/android/internal/app/AbstractResolverComparatorTest.java +++ b/core/tests/coretests/src/com/android/internal/app/AbstractResolverComparatorTest.java @@ -115,11 +115,6 @@ public class AbstractResolverComparatorTest { @Override void handleResultMessage(Message message) {} - - @Override - List<ComponentName> getTopComponentNames(int topK) { - return null; - } }; return testComparator; } diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java index cf78646a466f..b38e1c274b45 100644 --- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java +++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java @@ -81,7 +81,6 @@ import android.net.Uri; import android.os.UserHandle; import android.provider.DeviceConfig; import android.service.chooser.ChooserTarget; -import android.util.Log; import android.view.View; import androidx.annotation.CallSuper; @@ -623,7 +622,7 @@ public class ChooserActivityTest { List<ResolvedComponentInfo> stableCopy = createResolvedComponentsForTestWithOtherProfile(2, /* userId= */ 10); waitForIdle(); - Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS); + Thread.sleep(((ChooserActivity) activity).mListViewUpdateDelayMs); onView(first(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))) .perform(click()); @@ -1437,7 +1436,7 @@ public class ChooserActivityTest { // Thread.sleep shouldn't be a thing in an integration test but it's // necessary here because of the way the code is structured // TODO: restructure the tests b/129870719 - Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS); + Thread.sleep(((ChooserActivity) activity).mListViewUpdateDelayMs); assertThat("Chooser should have 3 targets (2 apps, 1 direct)", activity.getAdapter().getCount(), is(3)); @@ -1513,7 +1512,7 @@ public class ChooserActivityTest { // Thread.sleep shouldn't be a thing in an integration test but it's // necessary here because of the way the code is structured // TODO: restructure the tests b/129870719 - Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS); + Thread.sleep(((ChooserActivity) activity).mListViewUpdateDelayMs); assertThat("Chooser should have 3 targets (2 apps, 1 direct)", activity.getAdapter().getCount(), is(3)); @@ -1595,7 +1594,7 @@ public class ChooserActivityTest { // Thread.sleep shouldn't be a thing in an integration test but it's // necessary here because of the way the code is structured // TODO: restructure the tests b/129870719 - Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS); + Thread.sleep(((ChooserActivity) activity).mListViewUpdateDelayMs); assertThat("Chooser should have 3 targets (2 apps, 1 direct)", wrapper.getAdapter().getCount(), is(3)); @@ -1667,7 +1666,7 @@ public class ChooserActivityTest { // Thread.sleep shouldn't be a thing in an integration test but it's // necessary here because of the way the code is structured // TODO: restructure the tests b/129870719 - Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS); + Thread.sleep(((ChooserActivity) activity).mListViewUpdateDelayMs); assertThat("Chooser should have 4 targets (2 apps, 2 direct)", wrapper.getAdapter().getCount(), is(4)); @@ -1754,7 +1753,7 @@ public class ChooserActivityTest { // Thread.sleep shouldn't be a thing in an integration test but it's // necessary here because of the way the code is structured // TODO: restructure the tests b/129870719 - Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS); + Thread.sleep(((ChooserActivity) activity).mListViewUpdateDelayMs); assertThat( String.format("Chooser should have %d targets (%d apps, 1 direct, 15 A-Z)", @@ -1879,12 +1878,13 @@ public class ChooserActivityTest { return true; }; - mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test")); + final IChooserWrapper activity = (IChooserWrapper) + mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test")); waitForIdle(); onView(withTextFromRuntimeResource("resolver_work_tab")).perform(click()); waitForIdle(); // wait for the share sheet to expand - Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS); + Thread.sleep(((ChooserActivity) activity).mListViewUpdateDelayMs); onView(first(allOf( withText(workResolvedComponentInfos.get(0) @@ -2023,7 +2023,7 @@ public class ChooserActivityTest { .check(matches(isDisplayed())); } - @Test + @Test @Ignore("b/222124533") public void testAppTargetLogging() throws InterruptedException { Intent sendIntent = createSendTextIntent(); List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2); @@ -2042,6 +2042,10 @@ public class ChooserActivityTest { mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); + // TODO(b/222124533): other test cases use a timeout to make sure that the UI is fully + // populated; without one, this test flakes. Ideally we should address the need for a + // timeout everywhere instead of introducing one to fix this particular test. + assertThat(activity.getAdapter().getCount(), is(2)); onView(withIdFromRuntimeResource("profile_button")).check(doesNotExist()); @@ -2143,7 +2147,7 @@ public class ChooserActivityTest { // Thread.sleep shouldn't be a thing in an integration test but it's // necessary here because of the way the code is structured // TODO: restructure the tests b/129870719 - Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS); + Thread.sleep(((ChooserActivity) activity).mListViewUpdateDelayMs); assertThat("Chooser should have 3 targets (2 apps, 1 direct)", activity.getAdapter().getCount(), is(3)); @@ -2324,7 +2328,7 @@ public class ChooserActivityTest { assertThat(logger.numCalls(), is(6)); } - @Test + @Test @Ignore("b/222124533") public void testSwitchProfileLogging() throws InterruptedException { // enable the work tab feature flag ResolverActivity.ENABLE_TABBED_VIEW = true; @@ -3069,8 +3073,15 @@ public class ChooserActivityTest { // framework code on the device is up-to-date. // TODO: is there a better way to do this? (Other than abandoning inheritance-based DI wrapper?) private int getRuntimeResourceId(String name, String defType) { - int id = mActivityRule.getActivity().getResources().getIdentifier(name, defType, "android"); + int id = -1; + if (ChooserActivityOverrideData.getInstance().resources != null) { + id = ChooserActivityOverrideData.getInstance().resources.getIdentifier( + name, defType, "android"); + } else { + id = mActivityRule.getActivity().getResources().getIdentifier(name, defType, "android"); + } assertThat(id, greaterThan(0)); + return id; } } diff --git a/core/tests/coretests/src/com/android/internal/app/FakeResolverComparatorModel.java b/core/tests/coretests/src/com/android/internal/app/FakeResolverComparatorModel.java new file mode 100644 index 000000000000..fbbe57c8e325 --- /dev/null +++ b/core/tests/coretests/src/com/android/internal/app/FakeResolverComparatorModel.java @@ -0,0 +1,61 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.app; + +import android.content.ComponentName; +import android.content.pm.ResolveInfo; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +/** + * Basic {@link ResolverComparatorModel} implementation that sorts according to a pre-defined (or + * default) {@link java.util.Comparator}. + */ +public class FakeResolverComparatorModel implements ResolverComparatorModel { + private final Comparator<ResolveInfo> mComparator; + + public static FakeResolverComparatorModel makeModelFromComparator( + Comparator<ResolveInfo> comparator) { + return new FakeResolverComparatorModel(comparator); + } + + public static FakeResolverComparatorModel makeDefaultModel() { + return makeModelFromComparator(Comparator.comparing(ri -> ri.activityInfo.name)); + } + + @Override + public Comparator<ResolveInfo> getComparator() { + return mComparator; + } + + @Override + public float getScore(ComponentName name) { + return 0.0f; // Models are not required to provide numerical scores. + } + + @Override + public void notifyOnTargetSelected(ComponentName componentName) { + System.out.println( + "User selected " + componentName + " under model " + System.identityHashCode(this)); + } + + private FakeResolverComparatorModel(Comparator<ResolveInfo> comparator) { + mComparator = comparator; + } +}
\ No newline at end of file diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index 9b09616d4630..b84847110441 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -889,6 +889,12 @@ "group": "WM_SHOW_TRANSACTIONS", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, + "-1256520588": { + "message": "performEnableScreen: mDisplayEnabled=%b mForceDisplayEnabled=%b mShowingBootMessages=%b mSystemBooted=%b. %s", + "level": "INFO", + "group": "WM_DEBUG_BOOT", + "at": "com\/android\/server\/wm\/WindowManagerService.java" + }, "-1248645819": { "message": "\tAdd container=%s", "level": "DEBUG", @@ -1519,12 +1525,6 @@ "group": "WM_DEBUG_WINDOW_TRANSITIONS", "at": "com\/android\/server\/wm\/TransitionController.java" }, - "-618015844": { - "message": "performEnableScreen: mDisplayEnabled=%b mForceDisplayEnabled=%b mShowingBootMessages=%b mSystemBooted=%b mOnlyCore=%b. %s", - "level": "INFO", - "group": "WM_DEBUG_BOOT", - "at": "com\/android\/server\/wm\/WindowManagerService.java" - }, "-597091183": { "message": "Delete TaskDisplayArea uid=%d", "level": "VERBOSE", @@ -2137,6 +2137,12 @@ "group": "WM_DEBUG_RECENTS_ANIMATIONS", "at": "com\/android\/server\/wm\/RecentsAnimationController.java" }, + "25888308": { + "message": "Resize reasons for w=%s: %s configChanged=%b dragResizingChanged=%b", + "level": "VERBOSE", + "group": "WM_DEBUG_RESIZE", + "at": "com\/android\/server\/wm\/WindowState.java" + }, "35398067": { "message": "goodToGo(): onAnimationStart, transit=%s, apps=%d, wallpapers=%d, nonApps=%d", "level": "DEBUG", @@ -2797,12 +2803,6 @@ "group": "WM_DEBUG_FOCUS_LIGHT", "at": "com\/android\/server\/wm\/DisplayContent.java" }, - "625447638": { - "message": "Resize reasons for w=%s: %s configChanged=%b dragResizingChanged=%b reportOrientationChanged=%b", - "level": "VERBOSE", - "group": "WM_DEBUG_RESIZE", - "at": "com\/android\/server\/wm\/WindowState.java" - }, "628276090": { "message": "Delaying app transition for screen rotation animation to finish", "level": "VERBOSE", diff --git a/data/keyboards/Generic.kl b/data/keyboards/Generic.kl index c81473ddcfc6..c117816352c7 100644 --- a/data/keyboards/Generic.kl +++ b/data/keyboards/Generic.kl @@ -430,8 +430,8 @@ axis 0x05 RZ axis 0x06 THROTTLE axis 0x07 RUDDER axis 0x08 WHEEL -axis 0x09 GAS -axis 0x0a BRAKE +axis 0x09 RTRIGGER +axis 0x0a LTRIGGER axis 0x10 HAT_X axis 0x11 HAT_Y diff --git a/errorprone/Android.bp b/errorprone/Android.bp index a927f53e3b5f..8f32f0eab37f 100644 --- a/errorprone/Android.bp +++ b/errorprone/Android.bp @@ -1,4 +1,3 @@ - package { // See: http://go/android-license-faq // A large-scale-change added 'default_applicable_licenses' to import @@ -42,8 +41,10 @@ java_test_host { static_libs: [ "truth-prebuilt", "kxml2-2.3.0", + "compile-testing-prebuilt", "error_prone_android_framework_lib", "error_prone_test_helpers", + "google_java_format", "hamcrest-library", "hamcrest", "platform-test-annotations", diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/HideInCommentsChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/HideInCommentsChecker.java new file mode 100644 index 000000000000..07f1d4a09006 --- /dev/null +++ b/errorprone/java/com/google/errorprone/bugpatterns/android/HideInCommentsChecker.java @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.errorprone.bugpatterns.android; + +import static com.google.errorprone.BugPattern.LinkType.NONE; +import static com.google.errorprone.BugPattern.SeverityLevel.WARNING; +import static com.google.errorprone.matchers.Description.NO_MATCH; +import static com.google.errorprone.util.ASTHelpers.getStartPosition; +import static com.google.errorprone.util.ASTHelpers.getSymbol; + +import com.google.auto.service.AutoService; +import com.google.errorprone.BugPattern; +import com.google.errorprone.VisitorState; +import com.google.errorprone.bugpatterns.BugChecker; +import com.google.errorprone.fixes.SuggestedFix; +import com.google.errorprone.matchers.Description; +import com.google.errorprone.util.ASTHelpers; +import com.google.errorprone.util.ErrorProneToken; +import com.google.errorprone.util.ErrorProneTokens; +import com.sun.source.tree.ClassTree; +import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.tree.MethodTree; +import com.sun.source.tree.NewClassTree; +import com.sun.source.tree.Tree; +import com.sun.source.tree.VariableTree; +import com.sun.tools.javac.parser.Tokens; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +import javax.lang.model.element.ElementKind; + +/** + * Bug checker to warn about {@code @hide} directives in comments. + * + * {@code @hide} tags are only meaningful inside of Javadoc comments. Errorprone has checks for + * standard Javadoc tags but doesn't know anything about {@code @hide} since it's an Android + * specific tag. + */ +@AutoService(BugChecker.class) +@BugPattern( + name = "AndroidHideInComments", + summary = "Warns when there are @hide declarations in comments rather than javadoc", + linkType = NONE, + severity = WARNING) +public class HideInCommentsChecker extends BugChecker implements + BugChecker.CompilationUnitTreeMatcher { + + @Override + public Description matchCompilationUnit(CompilationUnitTree tree, VisitorState state) { + final Map<Integer, Tree> javadocableTrees = findJavadocableTrees(tree); + final String sourceCode = state.getSourceCode().toString(); + for (ErrorProneToken token : ErrorProneTokens.getTokens(sourceCode, state.context)) { + for (Tokens.Comment comment : token.comments()) { + if (!javadocableTrees.containsKey(token.pos())) { + continue; + } + generateFix(comment).ifPresent(fix -> { + final Tree javadocableTree = javadocableTrees.get(token.pos()); + state.reportMatch(describeMatch(javadocableTree, fix)); + }); + } + } + // We might have multiple matches, so report them via VisitorState rather than the return + // value from the match function. + return NO_MATCH; + } + + private static Optional<SuggestedFix> generateFix(Tokens.Comment comment) { + final String text = comment.getText(); + if (text.startsWith("/**")) { + return Optional.empty(); + } + + if (!text.contains("@hide")) { + return Optional.empty(); + } + + if (text.startsWith("/*")) { + final int pos = comment.getSourcePos(1); + return Optional.of(SuggestedFix.replace(pos, pos, "*")); + } else if (text.startsWith("//")) { + final int endPos = comment.getSourcePos(text.length() - 1); + final char endChar = text.charAt(text.length() - 1); + String javadocClose = " */"; + if (endChar != ' ') { + javadocClose = endChar + javadocClose; + } + final SuggestedFix fix = SuggestedFix.builder() + .replace(comment.getSourcePos(1), comment.getSourcePos(2), "**") + .replace(endPos, endPos + 1, javadocClose) + .build(); + return Optional.of(fix); + } + + return Optional.empty(); + } + + + private Map<Integer, Tree> findJavadocableTrees(CompilationUnitTree tree) { + Map<Integer, Tree> javadoccableTrees = new HashMap<>(); + new SuppressibleTreePathScanner<Void, Void>() { + @Override + public Void visitClass(ClassTree classTree, Void unused) { + javadoccableTrees.put(getStartPosition(classTree), classTree); + return super.visitClass(classTree, null); + } + + @Override + public Void visitMethod(MethodTree methodTree, Void unused) { + // Generated constructors never have comments + if (!ASTHelpers.isGeneratedConstructor(methodTree)) { + javadoccableTrees.put(getStartPosition(methodTree), methodTree); + } + return super.visitMethod(methodTree, null); + } + + @Override + public Void visitVariable(VariableTree variableTree, Void unused) { + ElementKind kind = getSymbol(variableTree).getKind(); + if (kind == ElementKind.FIELD) { + javadoccableTrees.put(getStartPosition(variableTree), variableTree); + } + if (kind == ElementKind.ENUM_CONSTANT) { + javadoccableTrees.put(getStartPosition(variableTree), variableTree); + if (variableTree.getInitializer() instanceof NewClassTree) { + // Skip the generated class definition + ClassTree classBody = + ((NewClassTree) variableTree.getInitializer()).getClassBody(); + if (classBody != null) { + scan(classBody.getMembers(), null); + } + return null; + } + } + return super.visitVariable(variableTree, null); + } + + }.scan(tree, null); + return javadoccableTrees; + } + +} diff --git a/errorprone/tests/java/com/google/errorprone/bugpatterns/android/HideInCommentsCheckerTest.java b/errorprone/tests/java/com/google/errorprone/bugpatterns/android/HideInCommentsCheckerTest.java new file mode 100644 index 000000000000..f3e6c72756e0 --- /dev/null +++ b/errorprone/tests/java/com/google/errorprone/bugpatterns/android/HideInCommentsCheckerTest.java @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.errorprone.bugpatterns.android; + +import static com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode.TEXT_MATCH; + +import com.google.errorprone.BugCheckerRefactoringTestHelper; +import com.google.errorprone.CompilationTestHelper; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class HideInCommentsCheckerTest { + private static final String REFACTORING_FILE = "Test.java"; + + private BugCheckerRefactoringTestHelper mRefactoringHelper; + private CompilationTestHelper mCompilationHelper; + + @Before + public void setUp() { + mRefactoringHelper = BugCheckerRefactoringTestHelper.newInstance( + HideInCommentsChecker.class, HideInCommentsCheckerTest.class); + mCompilationHelper = CompilationTestHelper.newInstance( + HideInCommentsChecker.class, HideInCommentsCheckerTest.class); + } + + + @Test + public void refactorSingleLineComment() { + mRefactoringHelper + .addInputLines( + REFACTORING_FILE, + "public class Test {", + " // Foo @hide", + " void foo() {}", + "}") + .addOutputLines( + REFACTORING_FILE, + "public class Test {", + " /** Foo @hide */", + " void foo() {}", + "}") + .doTest(TEXT_MATCH); + } + + @Test + public void refactorSingleLineComment_doesntAddUnnecessarySpace() { + mRefactoringHelper + .addInputLines( + REFACTORING_FILE, + "public class Test {", + " // Foo @hide ", + " void foo() {}", + "}") + .addOutputLines( + REFACTORING_FILE, + "public class Test {", + " /** Foo @hide */", + " void foo() {}", + "}") + .doTest(TEXT_MATCH); + } + + @Test + public void refactorSingleLineBlockComment() { + mRefactoringHelper + .addInputLines( + REFACTORING_FILE, + "public class Test {", + " /* Foo @hide */", + " void foo() {}", + "}") + .addOutputLines( + REFACTORING_FILE, + "public class Test {", + " /** Foo @hide */", + " void foo() {}", + "}") + .doTest(TEXT_MATCH); + } + + @Test + public void refactorMultiLineBlockComment() { + mRefactoringHelper + .addInputLines( + REFACTORING_FILE, + "public class Test {", + " /*", + " * Foo.", + " *", + " * @hide", + " */", + " void foo(int foo) {}", + "}") + .addOutputLines( + REFACTORING_FILE, + "public class Test {", + " /**", + " * Foo.", + " *", + " * @hide", + " */", + " void foo(int foo) {}", + "}") + .doTest(TEXT_MATCH); + } + + @Test + public void refactorFieldComment() { + mRefactoringHelper + .addInputLines( + REFACTORING_FILE, + "public class Test {", + " /* Foo @hide */", + " public int foo = 0;", + "}") + .addOutputLines( + REFACTORING_FILE, + "public class Test {", + " /** Foo @hide */", + " public int foo = 0;", + "}") + .doTest(TEXT_MATCH); + } + + @Test + public void refactorClassComment() { + mRefactoringHelper + .addInputLines( + REFACTORING_FILE, + "/* Foo @hide */", + "public class Test {}") + .addOutputLines( + REFACTORING_FILE, + "/** Foo @hide */", + "public class Test {}") + .doTest(TEXT_MATCH); + } + + @Test + public void refactorEnumComment() { + mRefactoringHelper + .addInputLines( + REFACTORING_FILE, + "public enum Test {", + " /* Foo @hide */", + " FOO", + "}") + .addOutputLines( + REFACTORING_FILE, + "public enum Test {", + " /** Foo @hide */", + " FOO", + "}") + .doTest(TEXT_MATCH); + } + + @Test + public void canBeSuppressed() { + mCompilationHelper + .addSourceLines( + REFACTORING_FILE, + "public class Test {", + " /* Foo @hide */", + " @SuppressWarnings(\"AndroidHideInComments\")", + " void foo() {}", + "}") + .doTest(); + } + + @Test + public void isInJavadoc() { + mCompilationHelper + .addSourceLines( + REFACTORING_FILE, + "public class Test {", + " /** Foo @hide */", + " void foo() {}", + "}") + .doTest(); + } + + @Test + public void isInMultilineJavadoc() { + mCompilationHelper + .addSourceLines( + REFACTORING_FILE, + "public class Test {", + " /**", + " * Foo.", + " *", + " * @hide", + " */", + " void foo(int foo) {}", + "}") + .doTest(); + } + + @Test + public void noHidePresent() { + mCompilationHelper + .addSourceLines( + "test/" + REFACTORING_FILE, + "package test;", + "// Foo.", + "public class Test {", + " // Foo.", + " public int a;", + " /*", + " * Foo.", + " *", + " */", + " void foo(int foo) {}", + "}") + .doTest(); + } + +} diff --git a/graphics/java/android/graphics/text/LineBreakConfig.java b/graphics/java/android/graphics/text/LineBreakConfig.java index d083e444e996..7ad9aecaf6a3 100644 --- a/graphics/java/android/graphics/text/LineBreakConfig.java +++ b/graphics/java/android/graphics/text/LineBreakConfig.java @@ -89,6 +89,11 @@ public final class LineBreakConfig { private @LineBreakWordStyle int mLineBreakWordStyle = LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE; + // Whether or not enabling phrase breaking automatically. + // TODO(b/226012260): Remove this and add LINE_BREAK_WORD_STYLE_PHRASE_AUTO after + // the experiment. + private boolean mAutoPhraseBreaking = false; + /** * Builder constructor with line break parameters. */ @@ -118,12 +123,22 @@ public final class LineBreakConfig { } /** + * Enable or disable the automation of {@link LINE_BREAK_WORD_STYLE_PHRASE}. + * + * @hide + */ + public @NonNull Builder setAutoPhraseBreaking(boolean autoPhraseBreaking) { + mAutoPhraseBreaking = autoPhraseBreaking; + return this; + } + + /** * Build the {@link LineBreakConfig} * * @return the LineBreakConfig instance. */ public @NonNull LineBreakConfig build() { - return new LineBreakConfig(mLineBreakStyle, mLineBreakWordStyle); + return new LineBreakConfig(mLineBreakStyle, mLineBreakWordStyle, mAutoPhraseBreaking); } } @@ -143,6 +158,23 @@ public final class LineBreakConfig { .build(); } + /** + * Create the LineBreakConfig instance. + * + * @param lineBreakStyle the line break style for text wrapping. + * @param lineBreakWordStyle the line break word style for text wrapping. + * @return the {@link LineBreakConfig} instance. * + * @hide + */ + public static @NonNull LineBreakConfig getLineBreakConfig(@LineBreakStyle int lineBreakStyle, + @LineBreakWordStyle int lineBreakWordStyle, boolean autoPhraseBreaking) { + LineBreakConfig.Builder builder = new LineBreakConfig.Builder(); + return builder.setLineBreakStyle(lineBreakStyle) + .setLineBreakWordStyle(lineBreakWordStyle) + .setAutoPhraseBreaking(autoPhraseBreaking) + .build(); + } + /** @hide */ public static final LineBreakConfig NONE = new Builder().setLineBreakStyle(LINE_BREAK_STYLE_NONE) @@ -150,15 +182,17 @@ public final class LineBreakConfig { private final @LineBreakStyle int mLineBreakStyle; private final @LineBreakWordStyle int mLineBreakWordStyle; + private final boolean mAutoPhraseBreaking; /** * Constructor with the line break parameters. * Use the {@link LineBreakConfig.Builder} to create the LineBreakConfig instance. */ private LineBreakConfig(@LineBreakStyle int lineBreakStyle, - @LineBreakWordStyle int lineBreakWordStyle) { + @LineBreakWordStyle int lineBreakWordStyle, boolean autoPhraseBreaking) { mLineBreakStyle = lineBreakStyle; mLineBreakWordStyle = lineBreakWordStyle; + mAutoPhraseBreaking = autoPhraseBreaking; } /** @@ -179,6 +213,17 @@ public final class LineBreakConfig { return mLineBreakWordStyle; } + /** + * Used to identify if the automation of {@link LINE_BREAK_WORD_STYLE_PHRASE} is enabled. + * + * @return The result that records whether or not the automation of + * {@link LINE_BREAK_WORD_STYLE_PHRASE} is enabled. + * @hide + */ + public boolean getAutoPhraseBreaking() { + return mAutoPhraseBreaking; + } + @Override public boolean equals(Object o) { if (o == null) return false; @@ -186,7 +231,8 @@ public final class LineBreakConfig { if (!(o instanceof LineBreakConfig)) return false; LineBreakConfig that = (LineBreakConfig) o; return (mLineBreakStyle == that.mLineBreakStyle) - && (mLineBreakWordStyle == that.mLineBreakWordStyle); + && (mLineBreakWordStyle == that.mLineBreakWordStyle) + && (mAutoPhraseBreaking == that.mAutoPhraseBreaking); } @Override diff --git a/identity/java/android/security/identity/CredstoreIdentityCredential.java b/identity/java/android/security/identity/CredstoreIdentityCredential.java index 8e011053d2a7..c591c879059c 100644 --- a/identity/java/android/security/identity/CredstoreIdentityCredential.java +++ b/identity/java/android/security/identity/CredstoreIdentityCredential.java @@ -38,8 +38,9 @@ import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.time.Instant; +import java.util.ArrayList; import java.util.Collection; -import java.util.LinkedList; +import java.util.List; import java.util.Map; import javax.crypto.BadPaddingException; @@ -227,7 +228,7 @@ class CredstoreIdentityCredential extends IdentityCredential { throw new RuntimeException("Error decoding certificates", e); } - LinkedList<X509Certificate> x509Certs = new LinkedList<>(); + ArrayList<X509Certificate> x509Certs = new ArrayList<>(); for (Certificate cert : certs) { x509Certs.add((X509Certificate) cert); } @@ -384,7 +385,7 @@ class CredstoreIdentityCredential extends IdentityCredential { public @NonNull Collection<X509Certificate> getAuthKeysNeedingCertification() { try { AuthKeyParcel[] authKeyParcels = mBinder.getAuthKeysNeedingCertification(); - LinkedList<X509Certificate> x509Certs = new LinkedList<>(); + ArrayList<X509Certificate> x509Certs = new ArrayList<>(); CertificateFactory factory = CertificateFactory.getInstance("X.509"); for (AuthKeyParcel authKeyParcel : authKeyParcels) { Collection<? extends Certificate> certs = null; diff --git a/identity/java/android/security/identity/CredstoreWritableIdentityCredential.java b/identity/java/android/security/identity/CredstoreWritableIdentityCredential.java index d2e7984ce19f..1ad70edb7c6f 100644 --- a/identity/java/android/security/identity/CredstoreWritableIdentityCredential.java +++ b/identity/java/android/security/identity/CredstoreWritableIdentityCredential.java @@ -25,8 +25,9 @@ import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; +import java.util.ArrayList; import java.util.Collection; -import java.util.LinkedList; +import java.util.List; class CredstoreWritableIdentityCredential extends WritableIdentityCredential { @@ -61,7 +62,7 @@ class CredstoreWritableIdentityCredential extends WritableIdentityCredential { throw new RuntimeException("Error decoding certificates", e); } - LinkedList<X509Certificate> x509Certs = new LinkedList<>(); + ArrayList<X509Certificate> x509Certs = new ArrayList<>(); for (Certificate cert : certs) { x509Certs.add((X509Certificate) cert); } diff --git a/identity/java/android/security/identity/PersonalizationData.java b/identity/java/android/security/identity/PersonalizationData.java index b34f2505a6a6..bdb00fdfb341 100644 --- a/identity/java/android/security/identity/PersonalizationData.java +++ b/identity/java/android/security/identity/PersonalizationData.java @@ -18,10 +18,11 @@ package android.security.identity; import android.annotation.NonNull; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashMap; -import java.util.LinkedList; +import java.util.List; /** * An object that holds personalization data. @@ -38,7 +39,7 @@ public class PersonalizationData { private PersonalizationData() { } - private LinkedList<AccessControlProfile> mProfiles = new LinkedList<>(); + private ArrayList<AccessControlProfile> mProfiles = new ArrayList<>(); private LinkedHashMap<String, NamespaceData> mNamespaces = new LinkedHashMap<>(); diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java index fdcb7be597d5..a20e7179daf1 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java @@ -22,7 +22,6 @@ import static androidx.window.common.CommonFoldingFeature.COMMON_STATE_UNKNOWN; import static androidx.window.common.CommonFoldingFeature.parseListFromString; import android.annotation.NonNull; -import android.annotation.Nullable; import android.content.Context; import android.hardware.devicestate.DeviceStateManager; import android.hardware.devicestate.DeviceStateManager.DeviceStateCallback; @@ -30,22 +29,25 @@ import android.text.TextUtils; import android.util.Log; import android.util.SparseIntArray; +import androidx.window.util.AcceptOnceConsumer; import androidx.window.util.BaseDataProducer; -import androidx.window.util.DataProducer; import com.android.internal.R; +import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.Optional; import java.util.Set; +import java.util.function.Consumer; /** - * An implementation of {@link androidx.window.util.DataProducer} that returns the device's posture - * by mapping the state returned from {@link DeviceStateManager} to values provided in the resources - * config at {@link R.array#config_device_state_postures}. + * An implementation of {@link androidx.window.util.BaseDataProducer} that returns + * the device's posture by mapping the state returned from {@link DeviceStateManager} to + * values provided in the resources' config at {@link R.array#config_device_state_postures}. */ -public final class DeviceStateManagerFoldingFeatureProducer extends - BaseDataProducer<List<CommonFoldingFeature>> { +public final class DeviceStateManagerFoldingFeatureProducer + extends BaseDataProducer<List<CommonFoldingFeature>> { private static final String TAG = DeviceStateManagerFoldingFeatureProducer.class.getSimpleName(); private static final boolean DEBUG = false; @@ -54,15 +56,11 @@ public final class DeviceStateManagerFoldingFeatureProducer extends private int mCurrentDeviceState = INVALID_DEVICE_STATE; - private final DeviceStateCallback mDeviceStateCallback = (state) -> { - mCurrentDeviceState = state; - notifyDataChanged(); - }; @NonNull - private final DataProducer<String> mRawFoldSupplier; + private final BaseDataProducer<String> mRawFoldSupplier; public DeviceStateManagerFoldingFeatureProducer(@NonNull Context context, - @NonNull DataProducer<String> rawFoldSupplier) { + @NonNull BaseDataProducer<String> rawFoldSupplier) { mRawFoldSupplier = rawFoldSupplier; String[] deviceStatePosturePairs = context.getResources() .getStringArray(R.array.config_device_state_postures); @@ -70,7 +68,8 @@ public final class DeviceStateManagerFoldingFeatureProducer extends String[] deviceStatePostureMapping = deviceStatePosturePair.split(":"); if (deviceStatePostureMapping.length != 2) { if (DEBUG) { - Log.e(TAG, "Malformed device state posture pair: " + deviceStatePosturePair); + Log.e(TAG, "Malformed device state posture pair: " + + deviceStatePosturePair); } continue; } @@ -82,7 +81,8 @@ public final class DeviceStateManagerFoldingFeatureProducer extends posture = Integer.parseInt(deviceStatePostureMapping[1]); } catch (NumberFormatException e) { if (DEBUG) { - Log.e(TAG, "Failed to parse device state or posture: " + deviceStatePosturePair, + Log.e(TAG, "Failed to parse device state or posture: " + + deviceStatePosturePair, e); } continue; @@ -92,32 +92,92 @@ public final class DeviceStateManagerFoldingFeatureProducer extends } if (mDeviceStateToPostureMap.size() > 0) { - context.getSystemService(DeviceStateManager.class) - .registerCallback(context.getMainExecutor(), mDeviceStateCallback); + DeviceStateCallback deviceStateCallback = (state) -> { + mCurrentDeviceState = state; + mRawFoldSupplier.getData(this::notifyFoldingFeatureChange); + }; + Objects.requireNonNull(context.getSystemService(DeviceStateManager.class)) + .registerCallback(context.getMainExecutor(), deviceStateCallback); } } - @Override - @Nullable - public Optional<List<CommonFoldingFeature>> getData() { - final int globalHingeState = globalHingeState(); - Optional<String> displayFeaturesString = mRawFoldSupplier.getData(); - if (displayFeaturesString.isEmpty() || TextUtils.isEmpty(displayFeaturesString.get())) { - return Optional.empty(); + /** + * Add a callback to mCallbacks if there is no device state. This callback will be run + * once a device state is set. Otherwise,run the callback immediately. + */ + private void runCallbackWhenValidState(@NonNull Consumer<List<CommonFoldingFeature>> callback, + String displayFeaturesString) { + if (isCurrentStateValid()) { + callback.accept(calculateFoldingFeature(displayFeaturesString)); + } else { + // This callback will be added to mCallbacks and removed once it runs once. + AcceptOnceConsumer<List<CommonFoldingFeature>> singleRunCallback = + new AcceptOnceConsumer<>(this, callback); + addDataChangedCallback(singleRunCallback); } - return Optional.of(parseListFromString(displayFeaturesString.get(), globalHingeState)); + } + + /** + * Checks to find {@link DeviceStateManagerFoldingFeatureProducer#mCurrentDeviceState} in the + * {@link DeviceStateManagerFoldingFeatureProducer#mDeviceStateToPostureMap} which was + * initialized in the constructor of {@link DeviceStateManagerFoldingFeatureProducer}. + * Returns a boolean value of whether the device state is valid. + */ + private boolean isCurrentStateValid() { + // If the device state is not found in the map, indexOfKey returns a negative number. + return mDeviceStateToPostureMap.indexOfKey(mCurrentDeviceState) >= 0; } @Override - protected void onListenersChanged(Set<Runnable> callbacks) { + protected void onListenersChanged( + @NonNull Set<Consumer<List<CommonFoldingFeature>>> callbacks) { super.onListenersChanged(callbacks); if (callbacks.isEmpty()) { - mRawFoldSupplier.removeDataChangedCallback(this::notifyDataChanged); + mCurrentDeviceState = INVALID_DEVICE_STATE; + mRawFoldSupplier.removeDataChangedCallback(this::notifyFoldingFeatureChange); } else { - mRawFoldSupplier.addDataChangedCallback(this::notifyDataChanged); + mRawFoldSupplier.addDataChangedCallback(this::notifyFoldingFeatureChange); } } + @NonNull + @Override + public Optional<List<CommonFoldingFeature>> getCurrentData() { + Optional<String> displayFeaturesString = mRawFoldSupplier.getCurrentData(); + if (!isCurrentStateValid()) { + return Optional.empty(); + } else { + return displayFeaturesString.map(this::calculateFoldingFeature); + } + } + + /** + * Adds the data to the storeFeaturesConsumer when the data is ready. + * @param storeFeaturesConsumer a consumer to collect the data when it is first available. + */ + public void getData(Consumer<List<CommonFoldingFeature>> storeFeaturesConsumer) { + mRawFoldSupplier.getData((String displayFeaturesString) -> { + if (TextUtils.isEmpty(displayFeaturesString)) { + storeFeaturesConsumer.accept(new ArrayList<>()); + } else { + runCallbackWhenValidState(storeFeaturesConsumer, displayFeaturesString); + } + }); + } + + private void notifyFoldingFeatureChange(String displayFeaturesString) { + if (TextUtils.isEmpty(displayFeaturesString)) { + notifyDataChanged(new ArrayList<>()); + } else { + notifyDataChanged(calculateFoldingFeature(displayFeaturesString)); + } + } + + private List<CommonFoldingFeature> calculateFoldingFeature(String displayFeaturesString) { + final int globalHingeState = globalHingeState(); + return parseListFromString(displayFeaturesString, globalHingeState); + } + private int globalHingeState() { return mDeviceStateToPostureMap.get(mCurrentDeviceState, COMMON_STATE_UNKNOWN); } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/RawFoldingFeatureProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/common/RawFoldingFeatureProducer.java index 69ad1badce60..7906342d445d 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/common/RawFoldingFeatureProducer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/common/RawFoldingFeatureProducer.java @@ -32,6 +32,7 @@ import com.android.internal.R; import java.util.Optional; import java.util.Set; +import java.util.function.Consumer; /** * Implementation of {@link androidx.window.util.DataProducer} that produces a @@ -40,7 +41,7 @@ import java.util.Set; * settings where the {@link String} property is saved with the key * {@link RawFoldingFeatureProducer#DISPLAY_FEATURES}. If this value is null or empty then the * value in {@link android.content.res.Resources} is used. If both are empty then - * {@link RawFoldingFeatureProducer#getData()} returns an empty object. + * {@link RawFoldingFeatureProducer#getData} returns an empty object. * {@link RawFoldingFeatureProducer} listens to changes in the setting so that it can override * the system {@link CommonFoldingFeature} data. */ @@ -63,12 +64,13 @@ public final class RawFoldingFeatureProducer extends BaseDataProducer<String> { @Override @NonNull - public Optional<String> getData() { + public void getData(Consumer<String> dataConsumer) { String displayFeaturesString = getFeatureString(); if (displayFeaturesString == null) { - return Optional.empty(); + dataConsumer.accept(""); + } else { + dataConsumer.accept(displayFeaturesString); } - return Optional.of(displayFeaturesString); } /** @@ -84,7 +86,7 @@ public final class RawFoldingFeatureProducer extends BaseDataProducer<String> { } @Override - protected void onListenersChanged(Set<Runnable> callbacks) { + protected void onListenersChanged(Set<Consumer<String>> callbacks) { if (callbacks.isEmpty()) { unregisterObserversIfNeeded(); } else { @@ -92,6 +94,12 @@ public final class RawFoldingFeatureProducer extends BaseDataProducer<String> { } } + @NonNull + @Override + public Optional<String> getCurrentData() { + return Optional.of(getFeatureString()); + } + /** * Registers settings observers, if needed. When settings observers are registered for this * producer callbacks for changes in data will be triggered. @@ -125,8 +133,8 @@ public final class RawFoldingFeatureProducer extends BaseDataProducer<String> { @Override public void onChange(boolean selfChange, Uri uri) { if (mDisplayFeaturesUri.equals(uri)) { - notifyDataChanged(); + notifyDataChanged(getFeatureString()); } } } -} +}
\ No newline at end of file diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java index a6f638822d10..792176b6d029 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java @@ -43,7 +43,6 @@ import androidx.window.util.DataProducer; import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.Set; import java.util.function.Consumer; @@ -63,7 +62,7 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { private final DataProducer<List<CommonFoldingFeature>> mFoldingFeatureProducer; - public WindowLayoutComponentImpl(Context context) { + public WindowLayoutComponentImpl(@NonNull Context context) { ((Application) context.getApplicationContext()) .registerActivityLifecycleCallbacks(new NotifyOnConfigurationChanged()); RawFoldingFeatureProducer foldingFeatureProducer = new RawFoldingFeatureProducer(context); @@ -81,7 +80,6 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { public void addWindowLayoutInfoListener(@NonNull Activity activity, @NonNull Consumer<WindowLayoutInfo> consumer) { mWindowLayoutChangeListeners.put(activity, consumer); - onDisplayFeaturesChanged(); } /** @@ -89,18 +87,8 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { * * @param consumer no longer interested in receiving updates to {@link WindowLayoutInfo} */ - public void removeWindowLayoutInfoListener( - @NonNull Consumer<WindowLayoutInfo> consumer) { + public void removeWindowLayoutInfoListener(@NonNull Consumer<WindowLayoutInfo> consumer) { mWindowLayoutChangeListeners.values().remove(consumer); - onDisplayFeaturesChanged(); - } - - void updateWindowLayout(@NonNull Activity activity, - @NonNull WindowLayoutInfo newLayout) { - Consumer<WindowLayoutInfo> consumer = mWindowLayoutChangeListeners.get(activity); - if (consumer != null) { - consumer.accept(newLayout); - } } @NonNull @@ -108,7 +96,6 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { return mWindowLayoutChangeListeners.keySet(); } - @NonNull private boolean isListeningForLayoutChanges(IBinder token) { for (Activity activity: getActivitiesListeningForLayoutChanges()) { if (token.equals(activity.getWindow().getAttributes().token)) { @@ -125,12 +112,12 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { /** * A convenience method to translate from the common feature state to the extensions feature * state. More specifically, translates from {@link CommonFoldingFeature.State} to - * {@link FoldingFeature.STATE_FLAT} or {@link FoldingFeature.STATE_HALF_OPENED}. If it is not + * {@link FoldingFeature#STATE_FLAT} or {@link FoldingFeature#STATE_HALF_OPENED}. If it is not * possible to translate, then we will return a {@code null} value. * * @param state if it matches a value in {@link CommonFoldingFeature.State}, {@code null} - * otherwise. @return a {@link FoldingFeature.STATE_FLAT} or - * {@link FoldingFeature.STATE_HALF_OPENED} if the given state matches a value in + * otherwise. @return a {@link FoldingFeature#STATE_FLAT} or + * {@link FoldingFeature#STATE_HALF_OPENED} if the given state matches a value in * {@link CommonFoldingFeature.State} and {@code null} otherwise. */ @Nullable @@ -144,17 +131,24 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { } } - private void onDisplayFeaturesChanged() { + private void onDisplayFeaturesChanged(List<CommonFoldingFeature> storedFeatures) { for (Activity activity : getActivitiesListeningForLayoutChanges()) { - WindowLayoutInfo newLayout = getWindowLayoutInfo(activity); - updateWindowLayout(activity, newLayout); + // Get the WindowLayoutInfo from the activity and pass the value to the layoutConsumer. + Consumer<WindowLayoutInfo> layoutConsumer = mWindowLayoutChangeListeners.get(activity); + WindowLayoutInfo newWindowLayout = getWindowLayoutInfo(activity, storedFeatures); + layoutConsumer.accept(newWindowLayout); } } - @NonNull - private WindowLayoutInfo getWindowLayoutInfo(@NonNull Activity activity) { - List<DisplayFeature> displayFeatures = getDisplayFeatures(activity); - return new WindowLayoutInfo(displayFeatures); + /** + * Translates the {@link DisplayFeature} into a {@link WindowLayoutInfo} when a + * valid state is found. + * @param activity a proxy for the {@link android.view.Window} that contains the + */ + private WindowLayoutInfo getWindowLayoutInfo( + @NonNull Activity activity, List<CommonFoldingFeature> storedFeatures) { + List<DisplayFeature> displayFeatureList = getDisplayFeatures(activity, storedFeatures); + return new WindowLayoutInfo(displayFeatureList); } /** @@ -172,26 +166,21 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { * * @param activity a proxy for the {@link android.view.Window} that contains the * {@link DisplayFeature}. - * @return a {@link List} of valid {@link DisplayFeature} that * are within the {@link android.view.Window} of the {@link Activity} */ - private List<DisplayFeature> getDisplayFeatures(@NonNull Activity activity) { + private List<DisplayFeature> getDisplayFeatures( + @NonNull Activity activity, List<CommonFoldingFeature> storedFeatures) { List<DisplayFeature> features = new ArrayList<>(); int displayId = activity.getDisplay().getDisplayId(); if (displayId != DEFAULT_DISPLAY) { Log.w(TAG, "This sample doesn't support display features on secondary displays"); return features; - } - - if (activity.isInMultiWindowMode()) { + } else if (activity.isInMultiWindowMode()) { // It is recommended not to report any display features in multi-window mode, since it // won't be possible to synchronize the display feature positions with window movement. return features; - } - - Optional<List<CommonFoldingFeature>> storedFeatures = mFoldingFeatureProducer.getData(); - if (storedFeatures.isPresent()) { - for (CommonFoldingFeature baseFeature : storedFeatures.get()) { + } else { + for (CommonFoldingFeature baseFeature : storedFeatures) { Integer state = convertToExtensionState(baseFeature.getState()); if (state == null) { continue; @@ -205,8 +194,8 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { features.add(new FoldingFeature(featureRect, baseFeature.getType(), state)); } } + return features; } - return features; } /** @@ -233,7 +222,8 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { private void onDisplayFeaturesChangedIfListening(Activity activity) { IBinder token = activity.getWindow().getAttributes().token; if (token == null || isListeningForLayoutChanges(token)) { - onDisplayFeaturesChanged(); + mFoldingFeatureProducer.getData( + WindowLayoutComponentImpl.this::onDisplayFeaturesChanged); } } } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java index 970f0a2af632..5bfb0ebdcaa8 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java @@ -28,41 +28,42 @@ import android.content.Context; import android.graphics.Rect; import android.os.Bundle; import android.os.IBinder; -import android.util.Log; import androidx.annotation.NonNull; import androidx.window.common.CommonFoldingFeature; import androidx.window.common.DeviceStateManagerFoldingFeatureProducer; import androidx.window.common.EmptyLifecycleCallbacksAdapter; import androidx.window.common.RawFoldingFeatureProducer; -import androidx.window.util.DataProducer; +import androidx.window.util.BaseDataProducer; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Optional; /** * Reference implementation of androidx.window.sidecar OEM interface for use with * WindowManager Jetpack. */ class SampleSidecarImpl extends StubSidecar { - private static final String TAG = "SampleSidecar"; - - private final DataProducer<List<CommonFoldingFeature>> mFoldingFeatureProducer; - + private List<CommonFoldingFeature> mStoredFeatures = new ArrayList<>(); SampleSidecarImpl(Context context) { ((Application) context.getApplicationContext()) .registerActivityLifecycleCallbacks(new NotifyOnConfigurationChanged()); - DataProducer<String> settingsFeatureProducer = new RawFoldingFeatureProducer(context); - mFoldingFeatureProducer = new DeviceStateManagerFoldingFeatureProducer(context, - settingsFeatureProducer); + BaseDataProducer<String> settingsFeatureProducer = new RawFoldingFeatureProducer(context); + BaseDataProducer<List<CommonFoldingFeature>> foldingFeatureProducer = + new DeviceStateManagerFoldingFeatureProducer(context, + settingsFeatureProducer); - mFoldingFeatureProducer.addDataChangedCallback(this::onDisplayFeaturesChanged); + foldingFeatureProducer.addDataChangedCallback(this::onDisplayFeaturesChanged); } - private void onDisplayFeaturesChanged() { + private void setStoredFeatures(List<CommonFoldingFeature> storedFeatures) { + mStoredFeatures = storedFeatures; + } + + private void onDisplayFeaturesChanged(List<CommonFoldingFeature> storedFeatures) { + setStoredFeatures(storedFeatures); updateDeviceState(getDeviceState()); for (IBinder windowToken : getWindowsListeningForLayoutChanges()) { SidecarWindowLayoutInfo newLayout = getWindowLayoutInfo(windowToken); @@ -79,16 +80,16 @@ class SampleSidecarImpl extends StubSidecar { } private int deviceStateFromFeature() { - List<CommonFoldingFeature> storedFeatures = mFoldingFeatureProducer.getData() - .orElse(Collections.emptyList()); - for (int i = 0; i < storedFeatures.size(); i++) { - CommonFoldingFeature feature = storedFeatures.get(i); + for (int i = 0; i < mStoredFeatures.size(); i++) { + CommonFoldingFeature feature = mStoredFeatures.get(i); final int state = feature.getState(); switch (state) { case CommonFoldingFeature.COMMON_STATE_FLAT: return SidecarDeviceState.POSTURE_OPENED; case CommonFoldingFeature.COMMON_STATE_HALF_OPENED: return SidecarDeviceState.POSTURE_HALF_OPENED; + case CommonFoldingFeature.COMMON_STATE_UNKNOWN: + return SidecarDeviceState.POSTURE_UNKNOWN; } } return SidecarDeviceState.POSTURE_UNKNOWN; @@ -109,7 +110,6 @@ class SampleSidecarImpl extends StubSidecar { private List<SidecarDisplayFeature> getDisplayFeatures(@NonNull Activity activity) { int displayId = activity.getDisplay().getDisplayId(); if (displayId != DEFAULT_DISPLAY) { - Log.w(TAG, "This sample doesn't support display features on secondary displays"); return Collections.emptyList(); } @@ -119,18 +119,15 @@ class SampleSidecarImpl extends StubSidecar { return Collections.emptyList(); } - Optional<List<CommonFoldingFeature>> storedFeatures = mFoldingFeatureProducer.getData(); List<SidecarDisplayFeature> features = new ArrayList<>(); - if (storedFeatures.isPresent()) { - for (CommonFoldingFeature baseFeature : storedFeatures.get()) { - SidecarDisplayFeature feature = new SidecarDisplayFeature(); - Rect featureRect = baseFeature.getRect(); - rotateRectToDisplayRotation(displayId, featureRect); - transformToWindowSpaceRect(activity, featureRect); - feature.setRect(featureRect); - feature.setType(baseFeature.getType()); - features.add(feature); - } + for (CommonFoldingFeature baseFeature : mStoredFeatures) { + SidecarDisplayFeature feature = new SidecarDisplayFeature(); + Rect featureRect = baseFeature.getRect(); + rotateRectToDisplayRotation(displayId, featureRect); + transformToWindowSpaceRect(activity, featureRect); + feature.setRect(featureRect); + feature.setType(baseFeature.getType()); + features.add(feature); } return Collections.unmodifiableList(features); } @@ -138,7 +135,7 @@ class SampleSidecarImpl extends StubSidecar { @Override protected void onListenersChanged() { if (hasListeners()) { - onDisplayFeaturesChanged(); + onDisplayFeaturesChanged(mStoredFeatures); } } @@ -158,7 +155,7 @@ class SampleSidecarImpl extends StubSidecar { private void onDisplayFeaturesChangedForActivity(@NonNull Activity activity) { IBinder token = activity.getWindow().getAttributes().token; if (token == null || mWindowLayoutChangeListenerTokens.contains(token)) { - onDisplayFeaturesChanged(); + onDisplayFeaturesChanged(mStoredFeatures); } } } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/util/AcceptOnceConsumer.java b/libs/WindowManager/Jetpack/src/androidx/window/util/AcceptOnceConsumer.java new file mode 100644 index 000000000000..7624b693ac43 --- /dev/null +++ b/libs/WindowManager/Jetpack/src/androidx/window/util/AcceptOnceConsumer.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.window.util; + +import android.annotation.NonNull; + +import java.util.function.Consumer; + +/** + * A base class that works with {@link BaseDataProducer} to add/remove a consumer that should + * only be used once when {@link BaseDataProducer#notifyDataChanged} is called. + * @param <T> The type of data this producer returns through {@link DataProducer#getData}. + */ +public class AcceptOnceConsumer<T> implements Consumer<T> { + private final Consumer<T> mCallback; + private final DataProducer<T> mProducer; + + public AcceptOnceConsumer(@NonNull DataProducer<T> producer, @NonNull Consumer<T> callback) { + mProducer = producer; + mCallback = callback; + } + + @Override + public void accept(@NonNull T t) { + mCallback.accept(t); + mProducer.removeDataChangedCallback(this); + } +} diff --git a/libs/WindowManager/Jetpack/src/androidx/window/util/BaseDataProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/util/BaseDataProducer.java index 930db3b701b7..0da44ac36a6e 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/util/BaseDataProducer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/util/BaseDataProducer.java @@ -19,38 +19,48 @@ package androidx.window.util; import androidx.annotation.NonNull; import java.util.LinkedHashSet; +import java.util.Optional; import java.util.Set; +import java.util.function.Consumer; /** * Base class that provides the implementation for the callback mechanism of the * {@link DataProducer} API. * - * @param <T> The type of data this producer returns through {@link #getData()}. + * @param <T> The type of data this producer returns through {@link DataProducer#getData}. */ public abstract class BaseDataProducer<T> implements DataProducer<T> { - private final Set<Runnable> mCallbacks = new LinkedHashSet<>(); + private final Set<Consumer<T>> mCallbacks = new LinkedHashSet<>(); @Override - public final void addDataChangedCallback(@NonNull Runnable callback) { + public final void addDataChangedCallback(@NonNull Consumer<T> callback) { mCallbacks.add(callback); + Optional<T> currentData = getCurrentData(); + currentData.ifPresent(callback); onListenersChanged(mCallbacks); } @Override - public final void removeDataChangedCallback(@NonNull Runnable callback) { + public final void removeDataChangedCallback(@NonNull Consumer<T> callback) { mCallbacks.remove(callback); onListenersChanged(mCallbacks); } - protected void onListenersChanged(Set<Runnable> callbacks) {} + protected void onListenersChanged(Set<Consumer<T>> callbacks) {} /** - * Called to notify all registered callbacks that the data provided by {@link #getData()} has - * changed. + * @return the current data if available and {@code Optional.empty()} otherwise. */ - protected void notifyDataChanged() { - for (Runnable callback : mCallbacks) { - callback.run(); + @NonNull + public abstract Optional<T> getCurrentData(); + + /** + * Called to notify all registered consumers that the data provided + * by {@link DataProducer#getData} has changed. + */ + protected void notifyDataChanged(T value) { + for (Consumer<T> callback : mCallbacks) { + callback.accept(value); } } -} +}
\ No newline at end of file diff --git a/libs/WindowManager/Jetpack/src/androidx/window/util/DataProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/util/DataProducer.java index d4d1a23b756b..ec301dc34aaa 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/util/DataProducer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/util/DataProducer.java @@ -18,26 +18,27 @@ package androidx.window.util; import android.annotation.NonNull; -import java.util.Optional; +import java.util.function.Consumer; /** - * Produces data through {@link #getData()} and provides a mechanism for receiving a callback when - * the data managed by the produces has changed. + * Produces data through {@link DataProducer#getData} and provides a mechanism for receiving + * a callback when the data managed by the produces has changed. * - * @param <T> The type of data this producer returns through {@link #getData()}. + * @param <T> The type of data this producer returns through {@link DataProducer#getData}. */ public interface DataProducer<T> { /** - * Returns the data currently stored in the provider, or {@link Optional#empty()} if the - * provider has no data. + * Emits the first available data at that point in time. + * @param dataConsumer a {@link Consumer} that will receive one value. */ - Optional<T> getData(); + void getData(@NonNull Consumer<T> dataConsumer); /** - * Adds a callback to be notified when the data returned from {@link #getData()} has changed. + * Adds a callback to be notified when the data returned + * from {@link DataProducer#getData} has changed. */ - void addDataChangedCallback(@NonNull Runnable callback); + void addDataChangedCallback(@NonNull Consumer<T> callback); - /** Removes a callback previously added with {@link #addDataChangedCallback(Runnable)}. */ - void removeDataChangedCallback(@NonNull Runnable callback); + /** Removes a callback previously added with {@link #addDataChangedCallback(Consumer)}. */ + void removeDataChangedCallback(@NonNull Consumer<T> callback); } diff --git a/libs/WindowManager/Shell/res/color/taskbar_background.xml b/libs/WindowManager/Shell/res/color/taskbar_background.xml index 329e5b9b31a0..b3d260299106 100644 --- a/libs/WindowManager/Shell/res/color/taskbar_background.xml +++ b/libs/WindowManager/Shell/res/color/taskbar_background.xml @@ -14,6 +14,7 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> +<!-- Should be the same as in packages/apps/Launcher3/res/color-v31/taskbar_background.xml --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:color="@android:color/system_neutral1_500" android:lStar="35" /> + <item android:color="@android:color/system_neutral1_500" android:lStar="15" /> </selector>
\ No newline at end of file diff --git a/libs/WindowManager/Shell/res/color/unfold_transition_background.xml b/libs/WindowManager/Shell/res/color/unfold_transition_background.xml deleted file mode 100644 index 63289a3f75d9..000000000000 --- a/libs/WindowManager/Shell/res/color/unfold_transition_background.xml +++ /dev/null @@ -1,19 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- 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. ---> -<selector xmlns:android="http://schemas.android.com/apk/res/android"> - <!-- Matches taskbar color --> - <item android:color="@android:color/system_neutral2_500" android:lStar="35" /> -</selector> diff --git a/libs/WindowManager/Shell/res/values-af/strings.xml b/libs/WindowManager/Shell/res/values-af/strings.xml index 88382d77ce35..2476f65c7e5b 100644 --- a/libs/WindowManager/Shell/res/values-af/strings.xml +++ b/libs/WindowManager/Shell/res/values-af/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Kamerakwessies?\nTik om aan te pas"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Nie opgelos nie?\nTik om terug te stel"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Geen kamerakwessies nie? Tik om toe te maak."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Sommige programme werk beter in portret"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Probeer een van hierdie opsies om jou spasie ten beste te benut"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Draai jou toestel om dit volskerm te maak"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Dubbeltik langs ’n program om dit te herposisioneer"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Het dit"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-af/strings_tv.xml b/libs/WindowManager/Shell/res/values-af/strings_tv.xml index 1bfe128b0917..c87bec093cca 100644 --- a/libs/WindowManager/Shell/res/values-af/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-af/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Maak PIP toe"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Volskerm"</string> <string name="pip_move" msgid="1544227837964635439">"Skuif PIP"</string> + <string name="pip_expand" msgid="7605396312689038178">"Vou PIP uit"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Vou PIP in"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Dubbeldruk "<annotation icon="home_icon">" TUIS "</annotation>" vir kontroles"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-am/strings.xml b/libs/WindowManager/Shell/res/values-am/strings.xml index 20d081f2f547..f0c391cd6b99 100644 --- a/libs/WindowManager/Shell/res/values-am/strings.xml +++ b/libs/WindowManager/Shell/res/values-am/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"የካሜራ ችግሮች አሉ?\nዳግም ለማበጀት መታ ያድርጉ"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"አልተስተካከለም?\nለማህደር መታ ያድርጉ"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"ምንም የካሜራ ችግሮች የሉም? ለማሰናበት መታ ያድርጉ።"</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"አንዳንድ መተግበሪያዎች በቁም ፎቶ ውስጥ በተሻለ ሁኔታ ይሰራሉ"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"ቦታዎን በአግባቡ ለመጠቀም ከእነዚህ አማራጮች ውስጥ አንዱን ይሞክሩ"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"ወደ የሙሉ ገጽ ዕይታ ለመሄድ መሣሪያዎን ያሽከርክሩት"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"ቦታውን ለመቀየር ከመተግበሪያው ቀጥሎ ላይ ሁለቴ መታ ያድርጉ"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"ገባኝ"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-am/strings_tv.xml b/libs/WindowManager/Shell/res/values-am/strings_tv.xml index 456b4b83583a..d23353858de6 100644 --- a/libs/WindowManager/Shell/res/values-am/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-am/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"PIPን ዝጋ"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"ሙሉ ማያ ገጽ"</string> <string name="pip_move" msgid="1544227837964635439">"ፒአይፒ ውሰድ"</string> + <string name="pip_expand" msgid="7605396312689038178">"ፒአይፒን ዘርጋ"</string> + <string name="pip_collapse" msgid="5732233773786896094">"ፒአይፒን ሰብስብ"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" ለመቆጣጠሪያዎች "<annotation icon="home_icon">"መነሻ"</annotation>"ን ሁለቴ ይጫኑ"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ar/strings.xml b/libs/WindowManager/Shell/res/values-ar/strings.xml index b41e6421ae55..aa4b3b704110 100644 --- a/libs/WindowManager/Shell/res/values-ar/strings.xml +++ b/libs/WindowManager/Shell/res/values-ar/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"هل هناك مشاكل في الكاميرا؟\nانقر لإعادة الضبط."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"ألم يتم حل المشكلة؟\nانقر للعودة"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"أليس هناك مشاكل في الكاميرا؟ انقر للإغلاق."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"تعمل بعض التطبيقات على أكمل وجه في الشاشات العمودية"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"جرِّب تنفيذ أحد هذه الخيارات للاستفادة من مساحتك إلى أقصى حد."</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"قم بتدوير الشاشة للانتقال إلى وضع ملء الشاشة."</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"انقر مرتين بجانب التطبيق لتغيير موضعه."</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"حسنًا"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ar/strings_tv.xml b/libs/WindowManager/Shell/res/values-ar/strings_tv.xml index 2546fe96d86a..a1ceda5fc987 100644 --- a/libs/WindowManager/Shell/res/values-ar/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-ar/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"إغلاق PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"ملء الشاشة"</string> <string name="pip_move" msgid="1544227837964635439">"نقل نافذة داخل النافذة (PIP)"</string> + <string name="pip_expand" msgid="7605396312689038178">"توسيع نافذة داخل النافذة (PIP)"</string> + <string name="pip_collapse" msgid="5732233773786896094">"تصغير نافذة داخل النافذة (PIP)"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" انقر مرتين على "<annotation icon="home_icon">" الصفحة الرئيسية "</annotation>" للوصول لعناصر التحكم."</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-as/strings.xml b/libs/WindowManager/Shell/res/values-as/strings.xml index 663691fdc045..985d3b9b96fd 100644 --- a/libs/WindowManager/Shell/res/values-as/strings.xml +++ b/libs/WindowManager/Shell/res/values-as/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"কেমেৰাৰ কোনো সমস্যা হৈছে নেকি?\nপুনৰ খাপ খোৱাবলৈ টিপক"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"এইটো সমাধান কৰা নাই নেকি?\nপূৰ্বাৱস্থালৈ নিবলৈ টিপক"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"কেমেৰাৰ কোনো সমস্যা নাই নেকি? অগ্ৰাহ্য কৰিবলৈ টিপক।"</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"কিছুমান এপে প’ৰ্ট্ৰেইট ম’ডত বেছি ভালকৈ কাম কৰে"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"আপোনাৰ spaceৰ পৰা পাৰ্যমানে উপকৃত হ’বলৈ ইয়াৰে এটা বিকল্প চেষ্টা কৰি চাওক"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"পূৰ্ণ স্ক্ৰীনলৈ যাবলৈ আপোনাৰ ডিভাইচটো ঘূৰাওক"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"এপ্টোৰ স্থান সলনি কৰিবলৈ ইয়াৰ কাষত দুবাৰ টিপক"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"বুজি পালোঁ"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-as/strings_tv.xml b/libs/WindowManager/Shell/res/values-as/strings_tv.xml index d17c1f3023a3..8d7bd9f6a27e 100644 --- a/libs/WindowManager/Shell/res/values-as/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-as/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"পিপ বন্ধ কৰক"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"সম্পূৰ্ণ স্ক্ৰীন"</string> <string name="pip_move" msgid="1544227837964635439">"পিপ স্থানান্তৰ কৰক"</string> + <string name="pip_expand" msgid="7605396312689038178">"পিপ বিস্তাৰ কৰক"</string> + <string name="pip_collapse" msgid="5732233773786896094">"পিপ সংকোচন কৰক"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" নিয়ন্ত্ৰণৰ বাবে "<annotation icon="home_icon">" গৃহপৃষ্ঠা "</annotation>" বুটামত দুবাৰ হেঁচক"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-az/strings.xml b/libs/WindowManager/Shell/res/values-az/strings.xml index 646aba89dd64..8cd9b7a635ab 100644 --- a/libs/WindowManager/Shell/res/values-az/strings.xml +++ b/libs/WindowManager/Shell/res/values-az/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Kamera problemi var?\nBərpa etmək üçün toxunun"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Düzəltməmisiniz?\nGeri qaytarmaq üçün toxunun"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Kamera problemi yoxdur? Qapatmaq üçün toxunun."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Bəzi tətbiqlər portret rejimində daha yaxşı işləyir"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Məkanınızdan maksimum yararlanmaq üçün bu seçimlərdən birini sınayın"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Tam ekrana keçmək üçün cihazınızı fırladın"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Tətbiqin yerini dəyişmək üçün yanına iki dəfə toxunun"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Anladım"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-az/strings_tv.xml b/libs/WindowManager/Shell/res/values-az/strings_tv.xml index a5c47924e31a..87c46fa41a01 100644 --- a/libs/WindowManager/Shell/res/values-az/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-az/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"PIP bağlayın"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Tam ekran"</string> <string name="pip_move" msgid="1544227837964635439">"PIP tətbiq edin"</string> + <string name="pip_expand" msgid="7605396312689038178">"PIP-ni genişləndirin"</string> + <string name="pip_collapse" msgid="5732233773786896094">"PIP-ni yığcamlaşdırın"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Nizamlayıcılar üçün "<annotation icon="home_icon">" ƏSAS SƏHİFƏ "</annotation>" süçimini iki dəfə basın"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml index 2ebdf926b357..49524c608543 100644 --- a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml +++ b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Imate problema sa kamerom?\nDodirnite da biste ponovo uklopili"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Problem nije rešen?\nDodirnite da biste vratili"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nemate problema sa kamerom? Dodirnite da biste odbacili."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Neke aplikacije najbolje funkcionišu u uspravnom režimu"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Isprobajte jednu od ovih opcija da biste na najbolji način iskoristili prostor"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Rotirajte uređaj za prikaz preko celog ekrana"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Dvaput dodirnite pored aplikacije da biste promenili njenu poziciju"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Važi"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings_tv.xml b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings_tv.xml index b4d9bd17b5fe..c87f30611a07 100644 --- a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Zatvori PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Ceo ekran"</string> <string name="pip_move" msgid="1544227837964635439">"Premesti sliku u slici"</string> + <string name="pip_expand" msgid="7605396312689038178">"Proširi sliku u slici"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Skupi sliku u slici"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Dvaput pritisnite "<annotation icon="home_icon">" HOME "</annotation>" za kontrole"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-be/strings.xml b/libs/WindowManager/Shell/res/values-be/strings.xml index 157e16895148..1767e0d66241 100644 --- a/libs/WindowManager/Shell/res/values-be/strings.xml +++ b/libs/WindowManager/Shell/res/values-be/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Праблемы з камерай?\nНацісніце, каб пераабсталяваць"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Не ўдалося выправіць?\nНацісніце, каб аднавіць"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Ніякіх праблем з камерай? Націсніце, каб адхіліць."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Некаторыя праграмы лепш за ўсё працуюць у кніжнай арыентацыі"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Каб эфектыўна выкарыстоўваць прастору, паспрабуйце адзін з гэтых варыянтаў"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Каб перайсці ў поўнаэкранны рэжым, павярніце прыладу"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Двойчы націсніце побач з праграмай, каб перамясціць яе"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Зразумела"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-be/strings_tv.xml b/libs/WindowManager/Shell/res/values-be/strings_tv.xml index 514d06b5b179..3566bc372820 100644 --- a/libs/WindowManager/Shell/res/values-be/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-be/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Закрыць PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Поўнаэкранны рэжым"</string> <string name="pip_move" msgid="1544227837964635439">"Перамясціць PIP"</string> + <string name="pip_expand" msgid="7605396312689038178">"Разгарнуць відарыс у відарысе"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Згарнуць відарыс у відарысе"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Двойчы націсніце "<annotation icon="home_icon">" ГАЛОЎНЫ ЭКРАН "</annotation>" для пераходу ў налады"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-bg/strings.xml b/libs/WindowManager/Shell/res/values-bg/strings.xml index 4ed8672db152..c22fb86a4d4d 100644 --- a/libs/WindowManager/Shell/res/values-bg/strings.xml +++ b/libs/WindowManager/Shell/res/values-bg/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Имате проблеми с камерата?\nДокоснете за ремонтиране"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Проблемът не се отстрани?\nДокоснете за връщане в предишното състояние"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Нямате проблеми с камерата? Докоснете, за да отхвърлите."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Някои приложения работят най-добре във вертикален режим"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Изпробвайте една от следните опции, за да се възползвате максимално от мястото на екрана"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Завъртете екрана си, за да преминете в режим на цял екран"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Докоснете два пъти дадено приложение, за да промените позицията му"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Разбрах"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-bg/strings_tv.xml b/libs/WindowManager/Shell/res/values-bg/strings_tv.xml index 19f83e71ea44..91049fd2cf02 100644 --- a/libs/WindowManager/Shell/res/values-bg/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-bg/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Затваряне на PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Цял екран"</string> <string name="pip_move" msgid="1544227837964635439">"„Картина в картина“: Преместв."</string> + <string name="pip_expand" msgid="7605396312689038178">"Разгъване на прозореца за PIP"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Свиване на прозореца за PIP"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" За достъп до контролите натиснете 2 пъти "<annotation icon="home_icon">"НАЧАЛО"</annotation></string> </resources> diff --git a/libs/WindowManager/Shell/res/values-bn/strings.xml b/libs/WindowManager/Shell/res/values-bn/strings.xml index 7579fac0ff06..c0944e0584e6 100644 --- a/libs/WindowManager/Shell/res/values-bn/strings.xml +++ b/libs/WindowManager/Shell/res/values-bn/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"ক্যামেরা সংক্রান্ত সমস্যা?\nরিফিট করতে ট্যাপ করুন"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"এখনও সমাধান হয়নি?\nরিভার্ট করার জন্য ট্যাপ করুন"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"ক্যামেরা সংক্রান্ত সমস্যা নেই? বাতিল করতে ট্যাপ করুন।"</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"কিছু অ্যাপ \'পোর্ট্রেট\' মোডে সবচেয়ে ভাল কাজ করে"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"আপনার স্পেস সবচেয়ে ভালভাবে কাজে লাগাতে এইসব বিকল্পের মধ্যে কোনও একটি ব্যবহার করে দেখুন"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"\'ফুল স্ক্রিন\' মোডে যেতে ডিভাইস ঘোরান"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"কোনও অ্যাপের পাশে ডবল ট্যাপ করে সেটির জায়গা পরিবর্তন করুন"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"বুঝেছি"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-bn/strings_tv.xml b/libs/WindowManager/Shell/res/values-bn/strings_tv.xml index 5f90eeb35a3f..792708d128a5 100644 --- a/libs/WindowManager/Shell/res/values-bn/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-bn/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"PIP বন্ধ করুন"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"পূর্ণ স্ক্রিন"</string> <string name="pip_move" msgid="1544227837964635439">"PIP সরান"</string> + <string name="pip_expand" msgid="7605396312689038178">"PIP বড় করুন"</string> + <string name="pip_collapse" msgid="5732233773786896094">"PIP আড়াল করুন"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" কন্ট্রোলের জন্য "<annotation icon="home_icon">" হোম "</annotation>" বোতামে ডবল প্রেস করুন"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-bs/strings.xml b/libs/WindowManager/Shell/res/values-bs/strings.xml index 7b08d035c7f2..ae01c641cc43 100644 --- a/libs/WindowManager/Shell/res/values-bs/strings.xml +++ b/libs/WindowManager/Shell/res/values-bs/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problemi s kamerom?\nDodirnite da ponovo namjestite"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Nije popravljeno?\nDodirnite da vratite"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nema problema s kamerom? Dodirnite da odbacite."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Određene aplikacije najbolje funkcioniraju u uspravnom načinu rada"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Isprobajte jednu od ovih opcija da maksimalno iskoristite prostor"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Zarotirajte uređaj da aktivirate prikaz preko cijelog ekrana"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Dvaput dodirnite pored aplikacije da promijenite njen položaj"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Razumijem"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-bs/strings_tv.xml b/libs/WindowManager/Shell/res/values-bs/strings_tv.xml index 3f2adf3600d7..b7f0dca1b5a5 100644 --- a/libs/WindowManager/Shell/res/values-bs/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-bs/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Zatvori sliku u slici"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Cijeli ekran"</string> <string name="pip_move" msgid="1544227837964635439">"Pokreni sliku u slici"</string> + <string name="pip_expand" msgid="7605396312689038178">"Proširi sliku u slici"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Suzi sliku u slici"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Dvaput pritisnite "<annotation icon="home_icon">" POČETNI EKRAN "</annotation>" za kontrole"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ca/strings.xml b/libs/WindowManager/Shell/res/values-ca/strings.xml index 44429cc582db..8a522b3e6397 100644 --- a/libs/WindowManager/Shell/res/values-ca/strings.xml +++ b/libs/WindowManager/Shell/res/values-ca/strings.xml @@ -27,7 +27,7 @@ <string name="pip_play" msgid="3496151081459417097">"Reprodueix"</string> <string name="pip_pause" msgid="690688849510295232">"Posa en pausa"</string> <string name="pip_skip_to_next" msgid="8403429188794867653">"Ves al següent"</string> - <string name="pip_skip_to_prev" msgid="7172158111196394092">"Torna a l\'anterior"</string> + <string name="pip_skip_to_prev" msgid="7172158111196394092">"Ves a l\'anterior"</string> <string name="accessibility_action_pip_resize" msgid="4623966104749543182">"Canvia la mida"</string> <string name="accessibility_action_pip_stash" msgid="4060775037619702641">"Amaga"</string> <string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Deixa d\'amagar"</string> @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Tens problemes amb la càmera?\nToca per resoldre\'ls"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"El problema no s\'ha resolt?\nToca per desfer els canvis"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"No tens cap problema amb la càmera? Toca per ignorar."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Algunes aplicacions funcionen millor en posició vertical"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Prova una d\'aquestes opcions per treure el màxim profit de l\'espai"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Gira el dispositiu per passar a pantalla completa"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Fes doble toc al costat d\'una aplicació per canviar-ne la posició"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Entesos"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ca/strings_tv.xml b/libs/WindowManager/Shell/res/values-ca/strings_tv.xml index db750c49884e..1c560c7afa06 100644 --- a/libs/WindowManager/Shell/res/values-ca/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-ca/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Tanca PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Pantalla completa"</string> <string name="pip_move" msgid="1544227837964635439">"Mou pantalla en pantalla"</string> + <string name="pip_expand" msgid="7605396312689038178">"Desplega pantalla en pantalla"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Replega pantalla en pantalla"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Prem dos cops "<annotation icon="home_icon">" INICI "</annotation>" per accedir als controls"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-cs/strings.xml b/libs/WindowManager/Shell/res/values-cs/strings.xml index d6e7136abb07..d0cf80aef38c 100644 --- a/libs/WindowManager/Shell/res/values-cs/strings.xml +++ b/libs/WindowManager/Shell/res/values-cs/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problémy s fotoaparátem?\nKlepnutím vyřešíte"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Nepomohlo to?\nKlepnutím se vrátíte"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Žádné problémy s fotoaparátem? Klepnutím zavřete."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Některé aplikace fungují nejlépe na výšku"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Pokud chcete maximálně využít prostor, vyzkoušejte jednu z těchto možností"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Otočením zařízení přejděte do režimu celé obrazovky"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Dvojitým klepnutím vedle aplikace změňte její umístění"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-cs/strings_tv.xml b/libs/WindowManager/Shell/res/values-cs/strings_tv.xml index cef0b9951363..9a8cc2b4d70e 100644 --- a/libs/WindowManager/Shell/res/values-cs/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-cs/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Ukončit obraz v obraze (PIP)"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Celá obrazovka"</string> <string name="pip_move" msgid="1544227837964635439">"Přesunout PIP"</string> + <string name="pip_expand" msgid="7605396312689038178">"Rozbalit PIP"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Sbalit PIP"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Ovládací prvky zobrazíte dvojitým stisknutím "<annotation icon="home_icon">"tlačítka plochy"</annotation></string> </resources> diff --git a/libs/WindowManager/Shell/res/values-da/strings.xml b/libs/WindowManager/Shell/res/values-da/strings.xml index e7b8e73b7385..bb81c10c6e1b 100644 --- a/libs/WindowManager/Shell/res/values-da/strings.xml +++ b/libs/WindowManager/Shell/res/values-da/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Har du problemer med dit kamera?\nTryk for at gendanne det oprindelige format"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Løste det ikke problemet?\nTryk for at fortryde"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Har du ingen problemer med dit kamera? Tryk for at afvise."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Nogle apps fungerer bedst i stående format"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Prøv én af disse muligheder for at få mest muligt ud af dit rum"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Drej din enhed for at gå til fuld skærm"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Tryk to gange ud for en app for at ændre dens placering"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-da/strings_tv.xml b/libs/WindowManager/Shell/res/values-da/strings_tv.xml index 23305309098d..cba660ac723c 100644 --- a/libs/WindowManager/Shell/res/values-da/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-da/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Luk integreret billede"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Fuld skærm"</string> <string name="pip_move" msgid="1544227837964635439">"Flyt PIP"</string> + <string name="pip_expand" msgid="7605396312689038178">"Udvid PIP"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Skjul PIP"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Tryk to gange på "<annotation icon="home_icon">" HJEM "</annotation>" for at se indstillinger"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-de/strings.xml b/libs/WindowManager/Shell/res/values-de/strings.xml index 57af696cacb1..c5d945a982ef 100644 --- a/libs/WindowManager/Shell/res/values-de/strings.xml +++ b/libs/WindowManager/Shell/res/values-de/strings.xml @@ -20,7 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Schließen"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Maximieren"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Einstellungen"</string> - <string name="pip_phone_enter_split" msgid="7042877263880641911">"„Bildschirm teilen“ aktivieren"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"„Geteilter Bildschirm“ aktivieren"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menü"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> ist in Bild im Bild"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Wenn du nicht möchtest, dass <xliff:g id="NAME">%s</xliff:g> diese Funktion verwendet, tippe, um die Einstellungen zu öffnen und die Funktion zu deaktivieren."</string> @@ -31,7 +31,7 @@ <string name="accessibility_action_pip_resize" msgid="4623966104749543182">"Größe anpassen"</string> <string name="accessibility_action_pip_stash" msgid="4060775037619702641">"In Stash legen"</string> <string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Aus Stash entfernen"</string> - <string name="dock_forced_resizable" msgid="1749750436092293116">"Die App funktioniert unter Umständen bei geteiltem Bildschirmmodus nicht."</string> + <string name="dock_forced_resizable" msgid="1749750436092293116">"Die App funktioniert unter Umständen im Modus für geteilten Bildschirm nicht."</string> <string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Das Teilen des Bildschirms wird in dieser App nicht unterstützt."</string> <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Die App funktioniert auf einem sekundären Display möglicherweise nicht."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Die App unterstützt den Start auf sekundären Displays nicht."</string> @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Probleme mit der Kamera?\nZum Anpassen tippen."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Das Problem ist nicht behoben?\nZum Rückgängigmachen tippen."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Keine Probleme mit der Kamera? Zum Schließen tippen."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Einige Apps funktionieren am besten im Hochformat"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Mithilfe dieser Möglichkeiten kannst du dein Display optimal nutzen"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Gerät drehen, um zum Vollbildmodus zu wechseln"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Neben einer App doppeltippen, um die Position zu ändern"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Ok"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-de/strings_tv.xml b/libs/WindowManager/Shell/res/values-de/strings_tv.xml index 8da9110f5e03..02a1b66eb63f 100644 --- a/libs/WindowManager/Shell/res/values-de/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-de/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"PIP schließen"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Vollbild"</string> <string name="pip_move" msgid="1544227837964635439">"BiB verschieben"</string> + <string name="pip_expand" msgid="7605396312689038178">"BiB maximieren"</string> + <string name="pip_collapse" msgid="5732233773786896094">"BiB minimieren"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Für Steuerelemente zweimal "<annotation icon="home_icon">"STARTBILDSCHIRMTASTE"</annotation>" drücken"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-el/strings.xml b/libs/WindowManager/Shell/res/values-el/strings.xml index 873b3299dcf1..70f55058925c 100644 --- a/libs/WindowManager/Shell/res/values-el/strings.xml +++ b/libs/WindowManager/Shell/res/values-el/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Προβλήματα με την κάμερα;\nΠατήστε για επιδιόρθωση."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Δεν διορθώθηκε;\nΠατήστε για επαναφορά."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Δεν αντιμετωπίζετε προβλήματα με την κάμερα; Πατήστε για παράβλεψη."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Ορισμένες εφαρμογές λειτουργούν καλύτερα σε κατακόρυφο προσανατολισμό"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Δοκιμάστε μία από αυτές τις επιλογές για να αξιοποιήσετε στο έπακρο τον χώρο σας."</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Περιστρέψτε τη συσκευή σας για μετάβαση σε πλήρη οθόνη."</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Πατήστε δύο φορές δίπλα σε μια εφαρμογή για να αλλάξετε τη θέση της."</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Το κατάλαβα"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-el/strings_tv.xml b/libs/WindowManager/Shell/res/values-el/strings_tv.xml index df35113a8752..24cd030cd754 100644 --- a/libs/WindowManager/Shell/res/values-el/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-el/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Κλείσιμο PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Πλήρης οθόνη"</string> <string name="pip_move" msgid="1544227837964635439">"Μετακίνηση PIP"</string> + <string name="pip_expand" msgid="7605396312689038178">"Ανάπτυξη PIP"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Σύμπτυξη PIP"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Πατήστε δύο φορές "<annotation icon="home_icon">" ΑΡΧΙΚΗ ΟΘΟΝΗ "</annotation>" για στοιχεία ελέγχου"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml index da4933b18a8f..0b5aefa5c72e 100644 --- a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml +++ b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Camera issues?\nTap to refit"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Didn’t fix it?\nTap to revert"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"No camera issues? Tap to dismiss."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Some apps work best in portrait"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Try one of these options to make the most of your space"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Rotate your device to go full screen"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Double-tap next to an app to reposition it"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Got it"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-en-rAU/strings_tv.xml b/libs/WindowManager/Shell/res/values-en-rAU/strings_tv.xml index 1fb319196bef..82257b42814d 100644 --- a/libs/WindowManager/Shell/res/values-en-rAU/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-en-rAU/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Close PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Full screen"</string> <string name="pip_move" msgid="1544227837964635439">"Move PIP"</string> + <string name="pip_expand" msgid="7605396312689038178">"Expand PIP"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Collapse PIP"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Double-press "<annotation icon="home_icon">" HOME "</annotation>" for controls"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml index da4933b18a8f..0b5aefa5c72e 100644 --- a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml +++ b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Camera issues?\nTap to refit"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Didn’t fix it?\nTap to revert"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"No camera issues? Tap to dismiss."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Some apps work best in portrait"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Try one of these options to make the most of your space"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Rotate your device to go full screen"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Double-tap next to an app to reposition it"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Got it"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-en-rCA/strings_tv.xml b/libs/WindowManager/Shell/res/values-en-rCA/strings_tv.xml index 1fb319196bef..82257b42814d 100644 --- a/libs/WindowManager/Shell/res/values-en-rCA/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-en-rCA/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Close PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Full screen"</string> <string name="pip_move" msgid="1544227837964635439">"Move PIP"</string> + <string name="pip_expand" msgid="7605396312689038178">"Expand PIP"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Collapse PIP"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Double-press "<annotation icon="home_icon">" HOME "</annotation>" for controls"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml index da4933b18a8f..0b5aefa5c72e 100644 --- a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml +++ b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Camera issues?\nTap to refit"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Didn’t fix it?\nTap to revert"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"No camera issues? Tap to dismiss."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Some apps work best in portrait"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Try one of these options to make the most of your space"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Rotate your device to go full screen"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Double-tap next to an app to reposition it"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Got it"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-en-rGB/strings_tv.xml b/libs/WindowManager/Shell/res/values-en-rGB/strings_tv.xml index 1fb319196bef..82257b42814d 100644 --- a/libs/WindowManager/Shell/res/values-en-rGB/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-en-rGB/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Close PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Full screen"</string> <string name="pip_move" msgid="1544227837964635439">"Move PIP"</string> + <string name="pip_expand" msgid="7605396312689038178">"Expand PIP"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Collapse PIP"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Double-press "<annotation icon="home_icon">" HOME "</annotation>" for controls"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml index da4933b18a8f..0b5aefa5c72e 100644 --- a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml +++ b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Camera issues?\nTap to refit"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Didn’t fix it?\nTap to revert"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"No camera issues? Tap to dismiss."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Some apps work best in portrait"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Try one of these options to make the most of your space"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Rotate your device to go full screen"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Double-tap next to an app to reposition it"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Got it"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-en-rIN/strings_tv.xml b/libs/WindowManager/Shell/res/values-en-rIN/strings_tv.xml index 1fb319196bef..82257b42814d 100644 --- a/libs/WindowManager/Shell/res/values-en-rIN/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-en-rIN/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Close PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Full screen"</string> <string name="pip_move" msgid="1544227837964635439">"Move PIP"</string> + <string name="pip_expand" msgid="7605396312689038178">"Expand PIP"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Collapse PIP"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Double-press "<annotation icon="home_icon">" HOME "</annotation>" for controls"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-en-rXC/strings_tv.xml b/libs/WindowManager/Shell/res/values-en-rXC/strings_tv.xml index 3b12d90f33a2..a6e494cfed3c 100644 --- a/libs/WindowManager/Shell/res/values-en-rXC/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-en-rXC/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Close PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Full screen"</string> <string name="pip_move" msgid="1544227837964635439">"Move PIP"</string> + <string name="pip_expand" msgid="7605396312689038178">"Expand PIP"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Collapse PIP"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Double press "<annotation icon="home_icon">" HOME "</annotation>" for controls"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml index 154c7abae42d..e523ae53b0cc 100644 --- a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml +++ b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"¿Tienes problemas con la cámara?\nPresiona para reajustarla"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"¿No se resolvió?\nPresiona para revertir los cambios"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"¿No tienes problemas con la cámara? Presionar para descartar."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Algunas apps funcionan mejor en modo vertical"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Prueba estas opciones para aprovechar al máximo tu espacio"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Rota el dispositivo para ver la pantalla completa"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Presiona dos veces junto a una app para cambiar su posición"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Entendido"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-es-rUS/strings_tv.xml b/libs/WindowManager/Shell/res/values-es-rUS/strings_tv.xml index 1beb0b5b6255..458f6b15b857 100644 --- a/libs/WindowManager/Shell/res/values-es-rUS/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-es-rUS/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Cerrar PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Pantalla completa"</string> <string name="pip_move" msgid="1544227837964635439">"Mover PIP"</string> + <string name="pip_expand" msgid="7605396312689038178">"Maximizar PIP"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Minimizar PIP"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Presiona dos veces "<annotation icon="home_icon">"INICIO"</annotation>" para ver los controles"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-es/strings.xml b/libs/WindowManager/Shell/res/values-es/strings.xml index e2fa3a0376e0..974960708190 100644 --- a/libs/WindowManager/Shell/res/values-es/strings.xml +++ b/libs/WindowManager/Shell/res/values-es/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"¿Problemas con la cámara?\nToca para reajustar"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"¿No se ha solucionado?\nToca para revertir"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"¿No hay problemas con la cámara? Toca para cerrar."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Algunas aplicaciones funcionan mejor en vertical"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Prueba una de estas opciones para sacar el máximo partido al espacio de tu pantalla"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Gira el dispositivo para ir al modo de pantalla completa"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Toca dos veces junto a una aplicación para cambiar su posición"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Entendido"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-es/strings_tv.xml b/libs/WindowManager/Shell/res/values-es/strings_tv.xml index d042b43c8ce8..0a690984dac5 100644 --- a/libs/WindowManager/Shell/res/values-es/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-es/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Cerrar PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Pantalla completa"</string> <string name="pip_move" msgid="1544227837964635439">"Mover imagen en imagen"</string> + <string name="pip_expand" msgid="7605396312689038178">"Mostrar imagen en imagen"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Ocultar imagen en imagen"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Pulsa dos veces "<annotation icon="home_icon">"INICIO"</annotation>" para ver los controles"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-et/strings.xml b/libs/WindowManager/Shell/res/values-et/strings.xml index da33f4d60d2a..a5f82a6452c4 100644 --- a/libs/WindowManager/Shell/res/values-et/strings.xml +++ b/libs/WindowManager/Shell/res/values-et/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Kas teil on kaameraprobleeme?\nPuudutage ümberpaigutamiseks."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Kas probleemi ei lahendatud?\nPuudutage ennistamiseks."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Kas kaameraprobleeme pole? Puudutage loobumiseks."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Mõni rakendus töötab kõige paremini vertikaalpaigutuses"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Proovige ühte neist valikutest, et oma ruumi parimal moel kasutada"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Pöörake seadet, et aktiveerida täisekraanirežiim"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Topeltpuudutage rakenduse kõrval, et selle asendit muuta"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Selge"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-et/strings_tv.xml b/libs/WindowManager/Shell/res/values-et/strings_tv.xml index 3da16db9e196..dc0232303a70 100644 --- a/libs/WindowManager/Shell/res/values-et/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-et/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Sule PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Täisekraan"</string> <string name="pip_move" msgid="1544227837964635439">"Teisalda PIP-režiimi"</string> + <string name="pip_expand" msgid="7605396312689038178">"Laienda PIP-akent"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Ahenda PIP-aken"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Nuppude nägemiseks vajutage 2 korda nuppu "<annotation icon="home_icon">"AVAKUVA"</annotation></string> </resources> diff --git a/libs/WindowManager/Shell/res/values-eu/strings.xml b/libs/WindowManager/Shell/res/values-eu/strings.xml index e0dd3ca2c9e3..caa335a96222 100644 --- a/libs/WindowManager/Shell/res/values-eu/strings.xml +++ b/libs/WindowManager/Shell/res/values-eu/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Arazoak dauzkazu kamerarekin?\nBerriro doitzeko, sakatu hau."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Ez al da konpondu?\nLeheneratzeko, sakatu hau."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Ez daukazu arazorik kamerarekin? Baztertzeko, sakatu hau."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Aplikazio batzuk orientazio bertikalean funtzionatzen dute hobekien"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Pantailako eremuari ahalik eta etekinik handiena ateratzeko, probatu aukera hauetakoren bat"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Pantaila osoko modua erabiltzeko, biratu gailua"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Aplikazioaren posizioa aldatzeko, sakatu birritan haren ondoko edozein toki"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Ados"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-eu/strings_tv.xml b/libs/WindowManager/Shell/res/values-eu/strings_tv.xml index e4b57baf1e5f..bce06da2c66f 100644 --- a/libs/WindowManager/Shell/res/values-eu/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-eu/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Itxi PIPa"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Pantaila osoa"</string> <string name="pip_move" msgid="1544227837964635439">"Mugitu pantaila txiki gainjarria"</string> + <string name="pip_expand" msgid="7605396312689038178">"Zabaldu pantaila txiki gainjarria"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Tolestu pantaila txiki gainjarria"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Kontrolatzeko aukerak atzitzeko, sakatu birritan "<annotation icon="home_icon">" HASIERA "</annotation></string> </resources> diff --git a/libs/WindowManager/Shell/res/values-fa/strings.xml b/libs/WindowManager/Shell/res/values-fa/strings.xml index 6fcb5ee7ad6d..761fb9ddeb2f 100644 --- a/libs/WindowManager/Shell/res/values-fa/strings.xml +++ b/libs/WindowManager/Shell/res/values-fa/strings.xml @@ -48,8 +48,8 @@ <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"تمامصفحه پایین"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"استفاده از حالت یکدستی"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"برای خارج شدن، از پایین صفحهنمایش تند بهطرف بالا بکشید یا در هر جایی از بالای برنامه که میخواهید ضربه بزنید"</string> - <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"آغاز «حالت تک حرکت»"</string> - <string name="accessibility_action_stop_one_handed" msgid="1369940261782179442">"خروج از «حالت تک حرکت»"</string> + <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"آغاز «حالت یکدستی»"</string> + <string name="accessibility_action_stop_one_handed" msgid="1369940261782179442">"خروج از «حالت یکدستی»"</string> <string name="bubbles_settings_button_description" msgid="1301286017420516912">"تنظیمات برای حبابکهای <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="bubble_overflow_button_content_description" msgid="8160974472718594382">"لبریزشده"</string> <string name="bubble_accessibility_action_add_back" msgid="1830101076853540953">"افزودن برگشت به پشته"</string> @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"دوربین مشکل دارد؟\nبرای تنظیم مجدد اندازه ضربه بزنید"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"مشکل برطرف نشد؟\nبرای برگرداندن ضربه بزنید"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"دوربین مشکلی ندارد؟ برای بستن ضربه بزنید."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"برخیاز برنامهها در حالت عمودی عملکرد بهتری دارند"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"با امتحان کردن یکی از این گزینهها، بیشترین بهره را از فضایتان ببرید"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"برای رفتن به حالت تمام صفحه، دستگاهتان را بچرخانید"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"در کنار برنامه دوضربه بزنید تا جابهجا شود"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"متوجهام"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-fa/strings_tv.xml b/libs/WindowManager/Shell/res/values-fa/strings_tv.xml index aaab34f807db..ff9a03c6cefb 100644 --- a/libs/WindowManager/Shell/res/values-fa/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-fa/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"بستن PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"تمام صفحه"</string> <string name="pip_move" msgid="1544227837964635439">"انتقال PIP (تصویر در تصویر)"</string> + <string name="pip_expand" msgid="7605396312689038178">"گسترده کردن «تصویر در تصویر»"</string> + <string name="pip_collapse" msgid="5732233773786896094">"جمع کردن «تصویر در تصویر»"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" برای کنترلها، دکمه "<annotation icon="home_icon">"صفحه اصلی"</annotation>" را دوبار فشار دهید"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-fi/strings.xml b/libs/WindowManager/Shell/res/values-fi/strings.xml index fc51ad4598b7..c809b4879e71 100644 --- a/libs/WindowManager/Shell/res/values-fi/strings.xml +++ b/libs/WindowManager/Shell/res/values-fi/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Onko kameran kanssa ongelmia?\nKorjaa napauttamalla"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Eikö ongelma ratkennut?\nKumoa napauttamalla"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Ei ongelmia kameran kanssa? Hylkää napauttamalla."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Osa sovelluksista toimii parhaiten pystytilassa"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Kokeile jotakin näistä vaihtoehdoista, jotta saat parhaan hyödyn näytön tilasta"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Käännä laitetta, niin se siirtyy koko näytön tilaan"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Kaksoisnapauta sovellusta, jos haluat siirtää sitä"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-fi/strings_tv.xml b/libs/WindowManager/Shell/res/values-fi/strings_tv.xml index 21c64633fac1..3e8bf9032780 100644 --- a/libs/WindowManager/Shell/res/values-fi/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-fi/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Sulje PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Koko näyttö"</string> <string name="pip_move" msgid="1544227837964635439">"Siirrä PIP"</string> + <string name="pip_expand" msgid="7605396312689038178">"Laajenna PIP"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Tiivistä PIP"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Asetukset: paina "<annotation icon="home_icon">"ALOITUSNÄYTTÖPAINIKETTA"</annotation>" kahdesti"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml index 43fad3a69f4d..62b2bb65a603 100644 --- a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml +++ b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problèmes d\'appareil photo?\nTouchez pour réajuster"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Problème non résolu?\nTouchez pour rétablir"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Aucun problème d\'appareil photo? Touchez pour ignorer."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Certaines applications fonctionnent mieux en mode portrait"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Essayez l\'une de ces options pour tirer le meilleur parti de votre espace"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Faites pivoter votre appareil pour passer en plein écran"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Touchez deux fois à côté d\'une application pour la repositionner"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-fr-rCA/strings_tv.xml b/libs/WindowManager/Shell/res/values-fr-rCA/strings_tv.xml index f4baaad13999..66e13b89c64b 100644 --- a/libs/WindowManager/Shell/res/values-fr-rCA/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-fr-rCA/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Fermer mode IDI"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Plein écran"</string> <string name="pip_move" msgid="1544227837964635439">"Déplacer l\'image incrustée"</string> + <string name="pip_expand" msgid="7605396312689038178">"Développer l\'image incrustée"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Réduire l\'image incrustée"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Appuyez deux fois sur "<annotation icon="home_icon">" ACCUEIL "</annotation>" pour les commandes"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-fr/strings.xml b/libs/WindowManager/Shell/res/values-fr/strings.xml index 8b8cc090eee5..b3e22af0a3e3 100644 --- a/libs/WindowManager/Shell/res/values-fr/strings.xml +++ b/libs/WindowManager/Shell/res/values-fr/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problèmes d\'appareil photo ?\nAppuyez pour réajuster"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Problème non résolu ?\nAppuyez pour rétablir"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Aucun problème d\'appareil photo ? Appuyez pour ignorer."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Certaines applis fonctionnent mieux en mode Portrait"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Essayez l\'une de ces options pour exploiter pleinement l\'espace"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Faites pivoter l\'appareil pour passer en plein écran"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Appuyez deux fois à côté d\'une appli pour la repositionner"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-fr/strings_tv.xml b/libs/WindowManager/Shell/res/values-fr/strings_tv.xml index 6ad8174db796..ed9baf5b6215 100644 --- a/libs/WindowManager/Shell/res/values-fr/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-fr/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Fermer mode PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Plein écran"</string> <string name="pip_move" msgid="1544227837964635439">"Déplacer le PIP"</string> + <string name="pip_expand" msgid="7605396312689038178">"Développer la fenêtre PIP"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Réduire la fenêtre PIP"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Menu de commandes : appuyez deux fois sur "<annotation icon="home_icon">"ACCUEIL"</annotation></string> </resources> diff --git a/libs/WindowManager/Shell/res/values-gl/strings.xml b/libs/WindowManager/Shell/res/values-gl/strings.xml index 9bc9d9338030..b8e039602243 100644 --- a/libs/WindowManager/Shell/res/values-gl/strings.xml +++ b/libs/WindowManager/Shell/res/values-gl/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Tes problemas coa cámara?\nToca para reaxustala"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Non se solucionaron os problemas?\nToca para reverter o seu tratamento"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Non hai problemas coa cámara? Tocar para ignorar."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Algunhas aplicacións funcionan mellor en modo vertical"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Proba unha destas opcións para sacar o máximo proveito do espazo da pantalla"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Xira o dispositivo para ver o contido en pantalla completa"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Toca dúas veces a carón dunha aplicación para cambiala de posición"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Entendido"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-gl/strings_tv.xml b/libs/WindowManager/Shell/res/values-gl/strings_tv.xml index dcb8709d010e..a057434d7853 100644 --- a/libs/WindowManager/Shell/res/values-gl/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-gl/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Pechar PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Pantalla completa"</string> <string name="pip_move" msgid="1544227837964635439">"Mover pantalla superposta"</string> + <string name="pip_expand" msgid="7605396312689038178">"Despregar pantalla superposta"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Contraer pantalla superposta"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Preme "<annotation icon="home_icon">"INICIO"</annotation>" dúas veces para acceder aos controis"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-gu/strings.xml b/libs/WindowManager/Shell/res/values-gu/strings.xml index 032b591de660..deda2d755e20 100644 --- a/libs/WindowManager/Shell/res/values-gu/strings.xml +++ b/libs/WindowManager/Shell/res/values-gu/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"કૅમેરામાં સમસ્યાઓ છે?\nફરીથી ફિટ કરવા માટે ટૅપ કરો"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"સુધારો નથી થયો?\nપહેલાંના પર પાછું ફેરવવા માટે ટૅપ કરો"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"કૅમેરામાં કોઈ સમસ્યા નથી? છોડી દેવા માટે ટૅપ કરો."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"અમુક ઍપ પોર્ટ્રેટ મોડમાં શ્રેષ્ઠ રીતે કાર્ય કરે છે"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"તમારી સ્પેસનો વધુને વધુ લાભ લેવા માટે, આ વિકલ્પોમાંથી કોઈ એક અજમાવો"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"પૂર્ણ સ્ક્રીન મોડ લાગુ કરવા માટે, તમારા ડિવાઇસને ફેરવો"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"કોઈ ઍપની જગ્યા બદલવા માટે, તેની બાજુમાં બે વાર ટૅપ કરો"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"સમજાઈ ગયું"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-gu/strings_tv.xml b/libs/WindowManager/Shell/res/values-gu/strings_tv.xml index ed815caaed0f..d9525910e4c6 100644 --- a/libs/WindowManager/Shell/res/values-gu/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-gu/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"PIP બંધ કરો"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"પૂર્ણ સ્ક્રીન"</string> <string name="pip_move" msgid="1544227837964635439">"PIP ખસેડો"</string> + <string name="pip_expand" msgid="7605396312689038178">"PIP મોટી કરો"</string> + <string name="pip_collapse" msgid="5732233773786896094">"PIP નાની કરો"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" નિયંત્રણો માટે "<annotation icon="home_icon">" હોમ "</annotation>" બટન પર બે વાર દબાવો"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-hi/strings.xml b/libs/WindowManager/Shell/res/values-hi/strings.xml index 72fd65ce55fd..36b11514c7e5 100644 --- a/libs/WindowManager/Shell/res/values-hi/strings.xml +++ b/libs/WindowManager/Shell/res/values-hi/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"क्या कैमरे से जुड़ी कोई समस्या है?\nफिर से फ़िट करने के लिए टैप करें"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"क्या समस्या ठीक नहीं हुई?\nपहले जैसा करने के लिए टैप करें"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"क्या कैमरे से जुड़ी कोई समस्या नहीं है? खारिज करने के लिए टैप करें."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"कुछ ऐप्लिकेशन, पोर्ट्रेट मोड में सबसे अच्छी तरह काम करते हैं"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"जगह का पूरा इस्तेमाल करने के लिए, इनमें से किसी एक विकल्प को आज़माएं"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"फ़ुल स्क्रीन मोड में जाने के लिए, डिवाइस को घुमाएं"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"किसी ऐप्लिकेशन की जगह बदलने के लिए, उसके बगल में दो बार टैप करें"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"ठीक है"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-hi/strings_tv.xml b/libs/WindowManager/Shell/res/values-hi/strings_tv.xml index 8bcc631b39a2..d897ac73f80d 100644 --- a/libs/WindowManager/Shell/res/values-hi/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-hi/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"PIP बंद करें"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"फ़ुल स्क्रीन"</string> <string name="pip_move" msgid="1544227837964635439">"पीआईपी को दूसरी जगह लेकर जाएं"</string> + <string name="pip_expand" msgid="7605396312689038178">"पीआईपी विंडो को बड़ा करें"</string> + <string name="pip_collapse" msgid="5732233773786896094">"पीआईपी विंडो को छोटा करें"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" कंट्रोल मेन्यू पर जाने के लिए, "<annotation icon="home_icon">" होम बटन"</annotation>" दो बार दबाएं"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-hr/strings.xml b/libs/WindowManager/Shell/res/values-hr/strings.xml index 5315558ea855..5ecc5585a6e9 100644 --- a/libs/WindowManager/Shell/res/values-hr/strings.xml +++ b/libs/WindowManager/Shell/res/values-hr/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problemi s fotoaparatom?\nDodirnite za popravak"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Problem nije riješen?\nDodirnite za vraćanje"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nemate problema s fotoaparatom? Dodirnite za odbacivanje."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Neke aplikacije najbolje funkcioniraju u portretnom usmjerenju"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Isprobajte jednu od ovih opcija da biste maksimalno iskoristili prostor"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Zakrenite uređaj radi prikaza na cijelom zaslonu"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Dvaput dodirnite pored aplikacije da biste joj promijenili položaj"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Shvaćam"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-hr/strings_tv.xml b/libs/WindowManager/Shell/res/values-hr/strings_tv.xml index 49b7ae0d7681..8f5f3164c4d7 100644 --- a/libs/WindowManager/Shell/res/values-hr/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-hr/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Zatvori PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Cijeli zaslon"</string> <string name="pip_move" msgid="1544227837964635439">"Premjesti PIP"</string> + <string name="pip_expand" msgid="7605396312689038178">"Proširi PIP"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Sažmi PIP"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Dvaput pritisnite "<annotation icon="home_icon">"POČETNI ZASLON"</annotation>" za kontrole"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-hu/strings.xml b/libs/WindowManager/Shell/res/values-hu/strings.xml index 01671c9ba1d5..2295250e2853 100644 --- a/libs/WindowManager/Shell/res/values-hu/strings.xml +++ b/libs/WindowManager/Shell/res/values-hu/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Kamerával kapcsolatos problémába ütközött?\nKoppintson a megoldáshoz."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Nem sikerült a hiba kijavítása?\nKoppintson a visszaállításhoz."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nincsenek problémái kamerával? Koppintson az elvetéshez."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Egyes alkalmazások álló tájolásban működnek a leghatékonyabban"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Próbálja ki az alábbi beállítások egyikét, hogy a legjobban ki tudja használni képernyő területét"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"A teljes képernyős mód elindításához forgassa el az eszközt"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Koppintson duplán az alkalmazás mellett az áthelyezéséhez"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Értem"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-hu/strings_tv.xml b/libs/WindowManager/Shell/res/values-hu/strings_tv.xml index 484db0cac067..fc8d79589121 100644 --- a/libs/WindowManager/Shell/res/values-hu/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-hu/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"PIP bezárása"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Teljes képernyő"</string> <string name="pip_move" msgid="1544227837964635439">"PIP áthelyezése"</string> + <string name="pip_expand" msgid="7605396312689038178">"Kép a képben kibontása"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Kép a képben összecsukása"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Vezérlők: "<annotation icon="home_icon">" KEZDŐKÉPERNYŐ "</annotation>" gomb kétszer megnyomva"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-hy/strings.xml b/libs/WindowManager/Shell/res/values-hy/strings.xml index 459cd0a6403c..208936539094 100644 --- a/libs/WindowManager/Shell/res/values-hy/strings.xml +++ b/libs/WindowManager/Shell/res/values-hy/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Տեսախցիկի հետ կապված խնդիրնե՞ր կան։\nՀպեք՝ վերակարգավորելու համար։"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Չհաջողվե՞ց շտկել։\nՀպեք՝ փոփոխությունները չեղարկելու համար։"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Տեսախցիկի հետ կապված խնդիրներ չկա՞ն։ Փակելու համար հպեք։"</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Որոշ հավելվածներ լավագույնս աշխատում են դիմանկարի ռեժիմում"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Փորձեք այս տարբերակներից մեկը՝ տարածքը հնարավորինս արդյունավետ օգտագործելու համար"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Պտտեք սարքը՝ լիաէկրան ռեժիմին անցնելու համար"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Կրկնակի հպեք հավելվածի կողքին՝ այն տեղափոխելու համար"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Եղավ"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-hy/strings_tv.xml b/libs/WindowManager/Shell/res/values-hy/strings_tv.xml index e447ffc0d964..f5665b8dd166 100644 --- a/libs/WindowManager/Shell/res/values-hy/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-hy/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Փակել PIP-ն"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Լիէկրան"</string> <string name="pip_move" msgid="1544227837964635439">"Տեղափոխել PIP-ը"</string> + <string name="pip_expand" msgid="7605396312689038178">"Ծավալել PIP-ը"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Ծալել PIP-ը"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Կարգավորումների համար կրկնակի սեղմեք "<annotation icon="home_icon">"ԳԼԽԱՎՈՐ ԷԿՐԱՆ"</annotation></string> </resources> diff --git a/libs/WindowManager/Shell/res/values-in/strings.xml b/libs/WindowManager/Shell/res/values-in/strings.xml index e5b7421bb97a..1b46b2fe2570 100644 --- a/libs/WindowManager/Shell/res/values-in/strings.xml +++ b/libs/WindowManager/Shell/res/values-in/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Masalah kamera?\nKetuk untuk memperbaiki"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Tidak dapat diperbaiki?\nKetuk untuk mengembalikan"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Tidak ada masalah kamera? Ketuk untuk menutup."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Beberapa aplikasi berfungsi paling baik dalam mode potret"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Coba salah satu opsi berikut untuk mengoptimalkan area layar Anda"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Putar perangkat untuk tampilan layar penuh"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Ketuk dua kali di samping aplikasi untuk mengubah posisinya"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Oke"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-in/strings_tv.xml b/libs/WindowManager/Shell/res/values-in/strings_tv.xml index b63170564734..a1535653f679 100644 --- a/libs/WindowManager/Shell/res/values-in/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-in/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Tutup PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Layar penuh"</string> <string name="pip_move" msgid="1544227837964635439">"Pindahkan PIP"</string> + <string name="pip_expand" msgid="7605396312689038178">"Luaskan PIP"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Ciutkan PIP"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Tekan dua kali "<annotation icon="home_icon">" HOME "</annotation>" untuk membuka kontrol"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-is/strings.xml b/libs/WindowManager/Shell/res/values-is/strings.xml index 1bfec2b9840b..a201c95137f3 100644 --- a/libs/WindowManager/Shell/res/values-is/strings.xml +++ b/libs/WindowManager/Shell/res/values-is/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Myndavélavesen?\nÝttu til að breyta stærð"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Ennþá vesen?\nÝttu til að afturkalla"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Ekkert myndavélavesen? Ýttu til að hunsa."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Sum forrit virka best í skammsniði"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Prófaðu einhvern af eftirfarandi valkostum til að nýta plássið sem best"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Snúðu tækinu til að nota allan skjáinn"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Ýttu tvisvar við hlið forritsins til að færa það"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Ég skil"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-is/strings_tv.xml b/libs/WindowManager/Shell/res/values-is/strings_tv.xml index 119ecf088c20..70ca1afe3aea 100644 --- a/libs/WindowManager/Shell/res/values-is/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-is/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Loka mynd í mynd"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Allur skjárinn"</string> <string name="pip_move" msgid="1544227837964635439">"Færa innfellda mynd"</string> + <string name="pip_expand" msgid="7605396312689038178">"Stækka innfellda mynd"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Minnka innfellda mynd"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Ýttu tvisvar á "<annotation icon="home_icon">" HEIM "</annotation>" til að opna stillingar"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-it/strings.xml b/libs/WindowManager/Shell/res/values-it/strings.xml index ebdf44b70551..7157ed088d30 100644 --- a/libs/WindowManager/Shell/res/values-it/strings.xml +++ b/libs/WindowManager/Shell/res/values-it/strings.xml @@ -46,10 +46,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Schermata superiore al 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Schermata superiore al 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Schermata inferiore a schermo intero"</string> - <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Usare la modalità one-hand"</string> + <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Usare la modalità a una mano"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Per uscire, scorri verso l\'alto dalla parte inferiore dello schermo oppure tocca un punto qualsiasi sopra l\'app"</string> - <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Avvia la modalità one-hand"</string> - <string name="accessibility_action_stop_one_handed" msgid="1369940261782179442">"Esci dalla modalità one-hand"</string> + <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Avvia la modalità a una mano"</string> + <string name="accessibility_action_stop_one_handed" msgid="1369940261782179442">"Esci dalla modalità a una mano"</string> <string name="bubbles_settings_button_description" msgid="1301286017420516912">"Impostazioni per bolle <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="bubble_overflow_button_content_description" msgid="8160974472718594382">"Altre"</string> <string name="bubble_accessibility_action_add_back" msgid="1830101076853540953">"Aggiungi di nuovo all\'elenco"</string> @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problemi con la fotocamera?\nTocca per risolverli"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Il problema non si è risolto?\nTocca per ripristinare"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nessun problema con la fotocamera? Tocca per ignorare."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Alcune app funzionano in modo ottimale in verticale"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Prova una di queste opzioni per ottimizzare lo spazio a tua disposizione"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Ruota il dispositivo per passare alla modalità a schermo intero"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Tocca due volte accanto a un\'app per riposizionarla"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-it/strings_tv.xml b/libs/WindowManager/Shell/res/values-it/strings_tv.xml index 92f015c387a0..cda627517872 100644 --- a/libs/WindowManager/Shell/res/values-it/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-it/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Chiudi PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Schermo intero"</string> <string name="pip_move" msgid="1544227837964635439">"Sposta PIP"</string> + <string name="pip_expand" msgid="7605396312689038178">"Espandi PIP"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Comprimi PIP"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Premi due volte "<annotation icon="home_icon">" HOME "</annotation>" per aprire i controlli"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-iw/strings.xml b/libs/WindowManager/Shell/res/values-iw/strings.xml index 3a0f72b1597c..52a6b0676222 100644 --- a/libs/WindowManager/Shell/res/values-iw/strings.xml +++ b/libs/WindowManager/Shell/res/values-iw/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"בעיות במצלמה?\nאפשר להקיש כדי לבצע התאמה מחדש"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"הבעיה לא נפתרה?\nאפשר להקיש כדי לחזור לגרסה הקודמת"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"אין בעיות במצלמה? אפשר להקיש כדי לסגור."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"חלק מהאפליקציות פועלות בצורה הטובה ביותר במצב תצוגה לאורך"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"כדי להפיק את המרב משטח המסך, ניתן לנסות את אחת מהאפשרויות האלה"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"מסובבים את המכשיר כדי לעבור לתצוגה במסך מלא"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"מקישים הקשה כפולה ליד אפליקציה כדי למקם אותה מחדש"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"הבנתי"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-iw/strings_tv.xml b/libs/WindowManager/Shell/res/values-iw/strings_tv.xml index d09b850d01d8..30ce97b998ca 100644 --- a/libs/WindowManager/Shell/res/values-iw/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-iw/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"סגירת PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"מסך מלא"</string> <string name="pip_move" msgid="1544227837964635439">"העברת תמונה בתוך תמונה (PIP)"</string> + <string name="pip_expand" msgid="7605396312689038178">"הרחבת חלון תמונה-בתוך-תמונה"</string> + <string name="pip_collapse" msgid="5732233773786896094">"כיווץ של חלון תמונה-בתוך-תמונה"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" לחיצה כפולה על "<annotation icon="home_icon">" הלחצן הראשי "</annotation>" תציג את אמצעי הבקרה"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ja/strings.xml b/libs/WindowManager/Shell/res/values-ja/strings.xml index 7b3ad248362d..5a25c24ba034 100644 --- a/libs/WindowManager/Shell/res/values-ja/strings.xml +++ b/libs/WindowManager/Shell/res/values-ja/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"カメラに関する問題の場合は、\nタップすると修正できます"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"修正されなかった場合は、\nタップすると元に戻ります"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"カメラに関する問題でない場合は、タップすると閉じます。"</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"アプリによっては縦向きにすると正常に動作します"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"スペースを最大限に活用するには、以下の方法のいずれかをお試しください"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"全画面表示にするにはデバイスを回転させてください"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"位置を変えるにはアプリの横をダブルタップしてください"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ja/strings_tv.xml b/libs/WindowManager/Shell/res/values-ja/strings_tv.xml index d6399e537894..e58e7bf6fabc 100644 --- a/libs/WindowManager/Shell/res/values-ja/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-ja/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"PIP を閉じる"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"全画面表示"</string> <string name="pip_move" msgid="1544227837964635439">"PIP を移動"</string> + <string name="pip_expand" msgid="7605396312689038178">"PIP を開く"</string> + <string name="pip_collapse" msgid="5732233773786896094">"PIP を閉じる"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" コントロールにアクセス: "<annotation icon="home_icon">" ホーム "</annotation>" を 2 回押します"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ka/strings.xml b/libs/WindowManager/Shell/res/values-ka/strings.xml index 07ee0f9910f7..bff86fa6ffe2 100644 --- a/libs/WindowManager/Shell/res/values-ka/strings.xml +++ b/libs/WindowManager/Shell/res/values-ka/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"კამერად პრობლემები აქვს?\nშეეხეთ გამოსასწორებლად"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"არ გამოსწორდა?\nშეეხეთ წინა ვერსიის დასაბრუნებლად"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"კამერას პრობლემები არ აქვს? შეეხეთ უარყოფისთვის."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"ზოგიერთი აპი უკეთ მუშაობს პორტრეტის რეჟიმში"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"გამოცადეთ ამ ვარიანტებიდან ერთ-ერთი, რათა მაქსიმალურად ისარგებლოთ თქვენი მეხსიერებით"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"მოატრიალეთ თქვენი მოწყობილობა სრული ეკრანის გასაშლელად"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"ორმაგად შეეხეთ აპის გვერდითა სივრცეს, რათა ის სხვაგან გადაიტანოთ"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"გასაგებია"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ka/strings_tv.xml b/libs/WindowManager/Shell/res/values-ka/strings_tv.xml index 8d7bee8f1398..b09686646c8b 100644 --- a/libs/WindowManager/Shell/res/values-ka/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-ka/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"PIP-ის დახურვა"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"სრულ ეკრანზე"</string> <string name="pip_move" msgid="1544227837964635439">"PIP გადატანა"</string> + <string name="pip_expand" msgid="7605396312689038178">"PIP-ის გაშლა"</string> + <string name="pip_collapse" msgid="5732233773786896094">"PIP-ის ჩაკეცვა"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" მართვის საშუალებებზე წვდომისთვის ორმაგად დააჭირეთ "<annotation icon="home_icon">" მთავარ ღილაკს "</annotation></string> </resources> diff --git a/libs/WindowManager/Shell/res/values-kk/strings.xml b/libs/WindowManager/Shell/res/values-kk/strings.xml index bdaa03eb5943..f57f3f581c85 100644 --- a/libs/WindowManager/Shell/res/values-kk/strings.xml +++ b/libs/WindowManager/Shell/res/values-kk/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Камерада қателер шықты ма?\nЖөндеу үшін түртіңіз."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Жөнделмеді ме?\nҚайтару үшін түртіңіз."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Камерада қателер шықпады ма? Жабу үшін түртіңіз."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Кейбір қолданба портреттік режимде жақсы жұмыс істейді"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Экранды тиімді пайдалану үшін мына опциялардың бірін байқап көріңіз."</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Толық экранға ауысу үшін құрылғыңызды бұрыңыз."</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Қолданбаның орнын ауыстыру үшін жанынан екі рет түртіңіз."</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Түсінікті"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-kk/strings_tv.xml b/libs/WindowManager/Shell/res/values-kk/strings_tv.xml index 05bdcc71f293..7bade0dff0d9 100644 --- a/libs/WindowManager/Shell/res/values-kk/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-kk/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"PIP жабу"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Толық экран"</string> <string name="pip_move" msgid="1544227837964635439">"PIP клипін жылжыту"</string> + <string name="pip_expand" msgid="7605396312689038178">"PIP терезесін жаю"</string> + <string name="pip_collapse" msgid="5732233773786896094">"PIP терезесін жию"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Басқару элементтері: "<annotation icon="home_icon">" НЕГІЗГІ ЭКРАН "</annotation>" түймесін екі рет басыңыз."</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-km/strings.xml b/libs/WindowManager/Shell/res/values-km/strings.xml index 2654765c22d9..5c04f881fe0e 100644 --- a/libs/WindowManager/Shell/res/values-km/strings.xml +++ b/libs/WindowManager/Shell/res/values-km/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"មានបញ្ហាពាក់ព័ន្ធនឹងកាមេរ៉ាឬ?\nចុចដើម្បីដោះស្រាយ"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"មិនបានដោះស្រាយបញ្ហានេះទេឬ?\nចុចដើម្បីត្រឡប់"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"មិនមានបញ្ហាពាក់ព័ន្ធនឹងកាមេរ៉ាទេឬ? ចុចដើម្បីច្រានចោល។"</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"កម្មវិធីមួយចំនួនដំណើរការបានប្រសើរបំផុតក្នុងទិសដៅបញ្ឈរ"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"សាកល្បងជម្រើសមួយក្នុងចំណោមទាំងនេះ ដើម្បីទទួលបានអត្ថប្រយោជន៍ច្រើនបំផុតពីកន្លែងទំនេររបស់អ្នក"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"បង្វិលឧបករណ៍របស់អ្នក ដើម្បីចូលប្រើអេក្រង់ពេញ"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"ចុចពីរដងនៅជាប់កម្មវិធីណាមួយ ដើម្បីប្ដូរទីតាំងកម្មវិធីនោះ"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"យល់ហើយ"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-km/strings_tv.xml b/libs/WindowManager/Shell/res/values-km/strings_tv.xml index e8315163ad46..721be1fc1650 100644 --- a/libs/WindowManager/Shell/res/values-km/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-km/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"បិទ PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"ពេញអេក្រង់"</string> <string name="pip_move" msgid="1544227837964635439">"ផ្លាស់ទី PIP"</string> + <string name="pip_expand" msgid="7605396312689038178">"ពង្រីក PIP"</string> + <string name="pip_collapse" msgid="5732233773786896094">"បង្រួម PIP"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" ចុចពីរដងលើ"<annotation icon="home_icon">"ប៊ូតុងដើម"</annotation>" ដើម្បីបើកផ្ទាំងគ្រប់គ្រង"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-kn/strings.xml b/libs/WindowManager/Shell/res/values-kn/strings.xml index 6edbf13d4e2e..e91383caa009 100644 --- a/libs/WindowManager/Shell/res/values-kn/strings.xml +++ b/libs/WindowManager/Shell/res/values-kn/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"ಕ್ಯಾಮರಾ ಸಮಸ್ಯೆಗಳಿವೆಯೇ?\nಮರುಹೊಂದಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"ಅದನ್ನು ಸರಿಪಡಿಸಲಿಲ್ಲವೇ?\nಹಿಂತಿರುಗಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"ಕ್ಯಾಮರಾ ಸಮಸ್ಯೆಗಳಿಲ್ಲವೇ? ವಜಾಗೊಳಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"ಕೆಲವು ಆ್ಯಪ್ಗಳು ಪೋರ್ಟ್ರೇಟ್ ಮೋಡ್ನಲ್ಲಿ ಅತ್ಯುತ್ತಮವಾಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತವೆ"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"ನಿಮ್ಮ ಸ್ಥಳಾವಕಾಶದ ಅತಿಹೆಚ್ಚು ಪ್ರಯೋಜನ ಪಡೆಯಲು ಈ ಆಯ್ಕೆಗಳಲ್ಲಿ ಒಂದನ್ನು ಬಳಸಿ ನೋಡಿ"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"ಪೂರ್ಣ ಸ್ಕ್ರೀನ್ಗೆ ಹೋಗಲು ನಿಮ್ಮ ಸಾಧನವನ್ನು ತಿರುಗಿಸಿ"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"ಆ್ಯಪ್ ಒಂದರ ಸ್ಥಾನವನ್ನು ಬದಲಾಯಿಸಲು ಅದರ ಪಕ್ಕದಲ್ಲಿ ಡಬಲ್-ಟ್ಯಾಪ್ ಮಾಡಿ"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"ಸರಿ"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-kn/strings_tv.xml b/libs/WindowManager/Shell/res/values-kn/strings_tv.xml index 305ef668cb58..8310c8a1169c 100644 --- a/libs/WindowManager/Shell/res/values-kn/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-kn/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"PIP ಮುಚ್ಚಿ"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"ಪೂರ್ಣ ಪರದೆ"</string> <string name="pip_move" msgid="1544227837964635439">"PIP ಅನ್ನು ಸರಿಸಿ"</string> + <string name="pip_expand" msgid="7605396312689038178">"ಚಿತ್ರದಲ್ಲಿ ಚಿತ್ರವನ್ನು ವಿಸ್ತರಿಸಿ"</string> + <string name="pip_collapse" msgid="5732233773786896094">"ಚಿತ್ರದಲ್ಲಿ ಚಿತ್ರವನ್ನು ಕುಗ್ಗಿಸಿ"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" ಕಂಟ್ರೋಲ್ಗಳಿಗಾಗಿ "<annotation icon="home_icon">" ಹೋಮ್ "</annotation>" ಅನ್ನು ಎರಡು ಬಾರಿ ಒತ್ತಿ"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ko/strings.xml b/libs/WindowManager/Shell/res/values-ko/strings.xml index 1f8d0b0b175d..104ba3f22c96 100644 --- a/libs/WindowManager/Shell/res/values-ko/strings.xml +++ b/libs/WindowManager/Shell/res/values-ko/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"카메라 문제가 있나요?\n해결하려면 탭하세요."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"해결되지 않았나요?\n되돌리려면 탭하세요."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"카메라에 문제가 없나요? 닫으려면 탭하세요."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"일부 앱은 세로 모드에서 가장 잘 작동함"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"공간을 최대한 이용할 수 있도록 이 옵션 중 하나를 시도해 보세요."</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"전체 화면 모드로 전환하려면 기기를 회전하세요."</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"앱 위치를 조정하려면 앱 옆을 두 번 탭하세요."</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"확인"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ko/strings_tv.xml b/libs/WindowManager/Shell/res/values-ko/strings_tv.xml index 76b0adfb3d88..a3e055a515a1 100644 --- a/libs/WindowManager/Shell/res/values-ko/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-ko/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"PIP 닫기"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"전체화면"</string> <string name="pip_move" msgid="1544227837964635439">"PIP 이동"</string> + <string name="pip_expand" msgid="7605396312689038178">"PIP 펼치기"</string> + <string name="pip_collapse" msgid="5732233773786896094">"PIP 접기"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" 제어 메뉴에 액세스하려면 "<annotation icon="home_icon">" 홈 "</annotation>"을 두 번 누르세요."</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ky/strings.xml b/libs/WindowManager/Shell/res/values-ky/strings.xml index 81eb2d70c2de..8203622a33fc 100644 --- a/libs/WindowManager/Shell/res/values-ky/strings.xml +++ b/libs/WindowManager/Shell/res/values-ky/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Камерада маселелер келип чыктыбы?\nОңдоо үчүн таптаңыз"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Оңдолгон жокпу?\nАртка кайтаруу үчүн таптаңыз"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Камерада маселе жокпу? Этибарга албоо үчүн таптаңыз."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Айрым колдонмолорду тигинен иштетүү туура болот"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Иш чөйрөсүнүн бардык мүмкүнчүлүктөрүн пайдалануу үчүн бул параметрлердин бирин колдонуп көрүңүз"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Толук экран режимине өтүү үчүн түзмөктү буруңуз"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Колдонмонун ракурсун өзгөртүү үчүн анын тушуна эки жолу басыңыз"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Түшүндүм"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ky/strings_tv.xml b/libs/WindowManager/Shell/res/values-ky/strings_tv.xml index 57b955a7c5d4..887ac52c8e43 100644 --- a/libs/WindowManager/Shell/res/values-ky/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-ky/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"PIP\'ти жабуу"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Толук экран"</string> <string name="pip_move" msgid="1544227837964635439">"PIP\'ти жылдыруу"</string> + <string name="pip_expand" msgid="7605396312689038178">"PIP\'ти жайып көрсөтүү"</string> + <string name="pip_collapse" msgid="5732233773786896094">"PIP\'ти жыйыштыруу"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Башкаруу элементтерин ачуу үчүн "<annotation icon="home_icon">" БАШКЫ БЕТ "</annotation>" баскычын эки жолу басыңыз"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-lo/strings.xml b/libs/WindowManager/Shell/res/values-lo/strings.xml index 325213020e5c..24396786f9d8 100644 --- a/libs/WindowManager/Shell/res/values-lo/strings.xml +++ b/libs/WindowManager/Shell/res/values-lo/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"ມີບັນຫາກ້ອງຖ່າຍຮູບບໍ?\nແຕະເພື່ອປັບໃໝ່"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"ບໍ່ໄດ້ແກ້ໄຂມັນບໍ?\nແຕະເພື່ອແປງກັບຄືນ"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"ບໍ່ມີບັນຫາກ້ອງຖ່າຍຮູບບໍ? ແຕະເພື່ອປິດໄວ້."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"ແອັບບາງຢ່າງເຮັດວຽກໄດ້ດີທີ່ສຸດໃນໂໝດລວງຕັ້ງ"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"ໃຫ້ລອງຕົວເລືອກໃດໜຶ່ງເຫຼົ່ານີ້ເພື່ອໃຊ້ປະໂຫຍດຈາກພື້ນທີ່ຂອງທ່ານໃຫ້ໄດ້ສູງສຸດ"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"ໝຸນອຸປະກອນຂອງທ່ານເພື່ອໃຊ້ແບບເຕັມຈໍ"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"ແຕະສອງເທື່ອໃສ່ຖັດຈາກແອັບໃດໜຶ່ງເພື່ອຈັດຕຳແໜ່ງຂອງມັນຄືນໃໝ່"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"ເຂົ້າໃຈແລ້ວ"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-lo/strings_tv.xml b/libs/WindowManager/Shell/res/values-lo/strings_tv.xml index cbea84ea7ea2..91c4a033356d 100644 --- a/libs/WindowManager/Shell/res/values-lo/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-lo/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"ປິດ PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"ເຕັມໜ້າຈໍ"</string> <string name="pip_move" msgid="1544227837964635439">"ຍ້າຍ PIP"</string> + <string name="pip_expand" msgid="7605396312689038178">"ຂະຫຍາຍ PIP"</string> + <string name="pip_collapse" msgid="5732233773786896094">"ຫຍໍ້ PIP ລົງ"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" ກົດ "<annotation icon="home_icon">" HOME "</annotation>" ສອງເທື່ອສຳລັບການຄວບຄຸມ"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-lt/strings.xml b/libs/WindowManager/Shell/res/values-lt/strings.xml index 70654c767287..e2ae643ad308 100644 --- a/libs/WindowManager/Shell/res/values-lt/strings.xml +++ b/libs/WindowManager/Shell/res/values-lt/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Iškilo problemų dėl kameros?\nPalieskite, kad pritaikytumėte iš naujo"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Nepavyko pataisyti?\nPalieskite, kad grąžintumėte"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nėra jokių problemų dėl kameros? Palieskite, kad atsisakytumėte."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Kai kurios programos geriausiai veikia stačiuoju režimu"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Pabandykite naudoti vieną iš šių parinkčių, kad išnaudotumėte visą vietą"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Pasukite įrenginį, kad įjungtumėte viso ekrano režimą"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Dukart palieskite šalia programos, kad pakeistumėte jos poziciją"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Supratau"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-lt/strings_tv.xml b/libs/WindowManager/Shell/res/values-lt/strings_tv.xml index 81716a609fc5..04265ca01b48 100644 --- a/libs/WindowManager/Shell/res/values-lt/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-lt/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Uždaryti PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Visas ekranas"</string> <string name="pip_move" msgid="1544227837964635439">"Perkelti PIP"</string> + <string name="pip_expand" msgid="7605396312689038178">"Iškleisti PIP"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Sutraukti PIP"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Jei reikia valdiklių, dukart paspauskite "<annotation icon="home_icon">"PAGRINDINIS"</annotation></string> </resources> diff --git a/libs/WindowManager/Shell/res/values-lv/strings.xml b/libs/WindowManager/Shell/res/values-lv/strings.xml index 74d1b3f6578c..a77160bc262a 100644 --- a/libs/WindowManager/Shell/res/values-lv/strings.xml +++ b/libs/WindowManager/Shell/res/values-lv/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Vai ir problēmas ar kameru?\nPieskarieties, lai tās novērstu."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Vai problēma netika novērsta?\nPieskarieties, lai atjaunotu."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Vai nav problēmu ar kameru? Pieskarieties, lai nerādītu."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Dažas lietotnes vislabāk darbojas portreta režīmā"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Izmēģiniet vienu no šīm iespējām, lai efektīvi izmantotu pieejamo vietu"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Pagrieziet ierīci, lai aktivizētu pilnekrāna režīmu"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Veiciet dubultskārienu blakus lietotnei, lai manītu tās pozīciju"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Labi"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-lv/strings_tv.xml b/libs/WindowManager/Shell/res/values-lv/strings_tv.xml index 5295cd230591..8c6191e00833 100644 --- a/libs/WindowManager/Shell/res/values-lv/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-lv/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Aizvērt PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Pilnekrāna režīms"</string> <string name="pip_move" msgid="1544227837964635439">"Pārvietot attēlu attēlā"</string> + <string name="pip_expand" msgid="7605396312689038178">"Izvērst “Attēls attēlā” logu"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Sakļaut “Attēls attēlā” logu"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Atvērt vadīklas: divreiz nospiediet pogu "<annotation icon="home_icon">"SĀKUMS"</annotation></string> </resources> diff --git a/libs/WindowManager/Shell/res/values-mk/strings.xml b/libs/WindowManager/Shell/res/values-mk/strings.xml index be6ed4d25ac1..bac0c9eee4c2 100644 --- a/libs/WindowManager/Shell/res/values-mk/strings.xml +++ b/libs/WindowManager/Shell/res/values-mk/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Проблеми со камерата?\nДопрете за да се совпадне повторно"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Не се поправи?\nДопрете за враќање"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Нема проблеми со камерата? Допрете за отфрлање."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Некои апликации најдобро работат во режим на портрет"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Испробајте една од опцииве за да го извлечете максимумот од вашиот простор"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Ротирајте го уредот за да отворите на цел екран"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Допрете двапати до некоја апликација за да ја преместите"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Сфатив"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-mk/strings_tv.xml b/libs/WindowManager/Shell/res/values-mk/strings_tv.xml index fa48a6cc1846..beef1fef862b 100644 --- a/libs/WindowManager/Shell/res/values-mk/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-mk/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Затвори PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Цел екран"</string> <string name="pip_move" msgid="1544227837964635439">"Премести PIP"</string> + <string name="pip_expand" msgid="7605396312689038178">"Прошири ја сликата во слика"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Собери ја сликата во слика"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Притиснете двапати на "<annotation icon="home_icon">" HOME "</annotation>" за контроли"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ml/strings.xml b/libs/WindowManager/Shell/res/values-ml/strings.xml index 14a341b49c0e..de0f837fcd3f 100644 --- a/libs/WindowManager/Shell/res/values-ml/strings.xml +++ b/libs/WindowManager/Shell/res/values-ml/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"ക്യാമറ പ്രശ്നങ്ങളുണ്ടോ?\nശരിയാക്കാൻ ടാപ്പ് ചെയ്യുക"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"അത് പരിഹരിച്ചില്ലേ?\nപുനഃസ്ഥാപിക്കാൻ ടാപ്പ് ചെയ്യുക"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"ക്യാമറാ പ്രശ്നങ്ങളൊന്നുമില്ലേ? നിരസിക്കാൻ ടാപ്പ് ചെയ്യുക."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"ചില ആപ്പുകൾ പോർട്രെയ്റ്റിൽ മികച്ച രീതിയിൽ പ്രവർത്തിക്കുന്നു"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"നിങ്ങളുടെ ഇടം പരമാവധി പ്രയോജനപ്പെടുത്താൻ ഈ ഓപ്ഷനുകളിലൊന്ന് പരീക്ഷിക്കുക"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"പൂർണ്ണ സ്ക്രീനിലേക്ക് മാറാൻ ഈ ഉപകരണം റൊട്ടേറ്റ് ചെയ്യുക"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"ഒരു ആപ്പിന്റെ സ്ഥാനം മാറ്റാൻ, അതിന് തൊട്ടടുത്ത് ഡബിൾ ടാപ്പ് ചെയ്യുക"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"മനസ്സിലായി"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ml/strings_tv.xml b/libs/WindowManager/Shell/res/values-ml/strings_tv.xml index 533375751378..c2a532d09647 100644 --- a/libs/WindowManager/Shell/res/values-ml/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-ml/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"PIP അടയ്ക്കുക"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"പൂര്ണ്ണ സ്ക്രീന്"</string> <string name="pip_move" msgid="1544227837964635439">"PIP നീക്കുക"</string> + <string name="pip_expand" msgid="7605396312689038178">"PIP വികസിപ്പിക്കുക"</string> + <string name="pip_collapse" msgid="5732233773786896094">"PIP ചുരുക്കുക"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" നിയന്ത്രണങ്ങൾക്കായി "<annotation icon="home_icon">" ഹോം "</annotation>" രണ്ട് തവണ അമർത്തുക"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-mn/strings.xml b/libs/WindowManager/Shell/res/values-mn/strings.xml index b59f2825b3b5..1205306e0833 100644 --- a/libs/WindowManager/Shell/res/values-mn/strings.xml +++ b/libs/WindowManager/Shell/res/values-mn/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Камерын асуудал гарсан уу?\nДахин тааруулахын тулд товшино уу"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Үүнийг засаагүй юу?\nБуцаахын тулд товшино уу"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Камерын асуудал байхгүй юу? Хаахын тулд товшино уу."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Зарим апп нь босоо чиглэлд хамгийн сайн ажилладаг"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Орон зайгаа сайтар ашиглахын тулд эдгээр сонголтуудын аль нэгийг туршиж үзээрэй"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Төхөөрөмжөө бүтэн дэлгэцээр үзэхийн тулд эргүүлнэ"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Аппыг дахин байрлуулахын тулд хажууд нь хоёр товшино"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Ойлголоо"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-mn/strings_tv.xml b/libs/WindowManager/Shell/res/values-mn/strings_tv.xml index ca1d27f29cdf..bf8c59b57359 100644 --- a/libs/WindowManager/Shell/res/values-mn/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-mn/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"PIP-г хаах"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Бүтэн дэлгэц"</string> <string name="pip_move" msgid="1544227837964635439">"PIP-г зөөх"</string> + <string name="pip_expand" msgid="7605396312689038178">"PIP-г дэлгэх"</string> + <string name="pip_collapse" msgid="5732233773786896094">"PIP-г хураах"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Хяналтад хандах бол "<annotation icon="home_icon">" HOME "</annotation>" дээр хоёр дарна уу"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-mr/strings.xml b/libs/WindowManager/Shell/res/values-mr/strings.xml index 3d2d6a36530c..c91d06fdf3d5 100644 --- a/libs/WindowManager/Shell/res/values-mr/strings.xml +++ b/libs/WindowManager/Shell/res/values-mr/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"कॅमेराशी संबंधित काही समस्या आहेत का?\nपुन्हा फिट करण्यासाठी टॅप करा"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"निराकरण झाले नाही?\nरिव्हर्ट करण्यासाठी कृपया टॅप करा"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"कॅमेराशी संबंधित कोणत्याही समस्या नाहीत का? डिसमिस करण्यासाठी टॅप करा."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"काही ॲप्स पोर्ट्रेटमध्ये सर्वोत्तम काम करतात"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"तुमच्या स्पेसचा पुरेपूर वापर करण्यासाठी, यांपैकी एक पर्याय वापरून पहा"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"फुल स्क्रीन करण्यासाठी, तुमचे डिव्हाइस फिरवा"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"ॲपची स्थिती पुन्हा बदलण्यासाठी, त्याच्या शेजारी दोनदा टॅप करा"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"समजले"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-mr/strings_tv.xml b/libs/WindowManager/Shell/res/values-mr/strings_tv.xml index 212bd21db344..5d519b7afe9a 100644 --- a/libs/WindowManager/Shell/res/values-mr/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-mr/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"PIP बंद करा"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"फुल स्क्रीन"</string> <string name="pip_move" msgid="1544227837964635439">"PIP हलवा"</string> + <string name="pip_expand" msgid="7605396312689038178">"PIP चा विस्तार करा"</string> + <string name="pip_collapse" msgid="5732233773786896094">"PIP कोलॅप्स करा"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" नियंत्रणांसाठी "<annotation icon="home_icon">" होम "</annotation>" दोनदा दाबा"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ms/strings.xml b/libs/WindowManager/Shell/res/values-ms/strings.xml index 4e9a7e952a09..652a9919d163 100644 --- a/libs/WindowManager/Shell/res/values-ms/strings.xml +++ b/libs/WindowManager/Shell/res/values-ms/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Isu kamera?\nKetik untuk memuatkan semula"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Isu tidak dibetulkan?\nKetik untuk kembali"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Tiada isu kamera? Ketik untuk mengetepikan."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Sesetengah apl berfungsi paling baik dalam mod potret"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Cuba salah satu daripada pilihan ini untuk memanfaatkan ruang anda sepenuhnya"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Putar peranti anda untuk beralih ke skrin penuh"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Ketik dua kali bersebelahan apl untuk menempatkan semula apl"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ms/strings_tv.xml b/libs/WindowManager/Shell/res/values-ms/strings_tv.xml index ce2912650da7..08642c47c91a 100644 --- a/libs/WindowManager/Shell/res/values-ms/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-ms/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Tutup PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Skrin penuh"</string> <string name="pip_move" msgid="1544227837964635439">"Alihkan PIP"</string> + <string name="pip_expand" msgid="7605396312689038178">"Kembangkan PIP"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Kuncupkan PIP"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Tekan dua kali "<annotation icon="home_icon">" LAMAN UTAMA "</annotation>" untuk mengakses kawalan"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-my/strings.xml b/libs/WindowManager/Shell/res/values-my/strings.xml index 449e50257d42..15d182c6451e 100644 --- a/libs/WindowManager/Shell/res/values-my/strings.xml +++ b/libs/WindowManager/Shell/res/values-my/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"ကင်မရာပြဿနာလား။\nပြင်ဆင်ရန် တို့ပါ"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"ကောင်းမသွားဘူးလား။\nပြန်ပြောင်းရန် တို့ပါ"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"ကင်မရာပြဿနာ မရှိဘူးလား။ ပယ်ရန် တို့ပါ။"</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"အချို့အက်ပ်များသည် ဒေါင်လိုက်တွင် အကောင်းဆုံးလုပ်ဆောင်သည်"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"သင့်နေရာကို အကောင်းဆုံးအသုံးပြုနိုင်ရန် ဤရွေးစရာများထဲမှ တစ်ခုကို စမ်းကြည့်ပါ"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"ဖန်သားပြင်အပြည့်လုပ်ရန် သင့်စက်ကို လှည့်နိုင်သည်"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"အက်ပ်နေရာပြန်ချရန် ၎င်းဘေးတွင် နှစ်ချက်တို့နိုင်သည်"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"ရပြီ"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-my/strings_tv.xml b/libs/WindowManager/Shell/res/values-my/strings_tv.xml index 4847742130ba..e01daee115ca 100644 --- a/libs/WindowManager/Shell/res/values-my/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-my/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"PIP ကိုပိတ်ပါ"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"မျက်နှာပြင် အပြည့်"</string> <string name="pip_move" msgid="1544227837964635439">"PIP ရွှေ့ရန်"</string> + <string name="pip_expand" msgid="7605396312689038178">"PIP ကို ချဲ့ရန်"</string> + <string name="pip_collapse" msgid="5732233773786896094">"PIP ကို လျှော့ပြပါ"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" ထိန်းချုပ်မှုအတွက် "<annotation icon="home_icon">" ပင်မခလုတ် "</annotation>" နှစ်ချက်နှိပ်ပါ"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-nb/strings.xml b/libs/WindowManager/Shell/res/values-nb/strings.xml index 2172cc5d3815..9fd42b2f129c 100644 --- a/libs/WindowManager/Shell/res/values-nb/strings.xml +++ b/libs/WindowManager/Shell/res/values-nb/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Har du kameraproblemer?\nTrykk for å tilpasse"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Ble ikke problemet løst?\nTrykk for å gå tilbake"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Har du ingen kameraproblemer? Trykk for å lukke."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Noen apper fungerer best i stående format"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Prøv et av disse alternativene for å få mest mulig ut av plassen din"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Roter enheten for å starte fullskjerm"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Dobbelttrykk ved siden av en app for å flytte den"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Greit"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-nb/strings_tv.xml b/libs/WindowManager/Shell/res/values-nb/strings_tv.xml index 7cef11c424ce..65ed0b7f5bff 100644 --- a/libs/WindowManager/Shell/res/values-nb/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-nb/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Lukk PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Fullskjerm"</string> <string name="pip_move" msgid="1544227837964635439">"Flytt BIB"</string> + <string name="pip_expand" msgid="7605396312689038178">"Vis BIB"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Skjul BIB"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Dobbelttrykk på "<annotation icon="home_icon">"HJEM"</annotation>" for å åpne kontroller"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ne/strings.xml b/libs/WindowManager/Shell/res/values-ne/strings.xml index ff01dcd9ff2d..8dfec88cc29d 100644 --- a/libs/WindowManager/Shell/res/values-ne/strings.xml +++ b/libs/WindowManager/Shell/res/values-ne/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"क्यामेरासम्बन्धी समस्या देखियो?\nसमस्या हल गर्न ट्याप गर्नुहोस्"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"समस्या हल भएन?\nपहिलेको जस्तै बनाउन ट्याप गर्नुहोस्"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"क्यामेरासम्बन्धी कुनै पनि समस्या छैन? खारेज गर्न ट्याप गर्नुहोस्।"</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"केही एपहरूले पोर्ट्रेटमा राम्रोसँग काम गर्छन्"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"तपाईं स्क्रिनको अधिकतम ठाउँ प्रयोग गर्न चाहनुहुन्छ भने यीमध्ये कुनै विकल्प प्रयोग गरी हेर्नुहोस्"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"तपाईं फुल स्क्रिन मोड हेर्न चाहनुहुन्छ भने आफ्नो डिभाइस रोटेट गर्नुहोस्"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"तपाईं जुन एपको स्थिति मिलाउन चाहनुहुन्छ सोही एपको छेउमा डबल ट्याप गर्नुहोस्"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"बुझेँ"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ne/strings_tv.xml b/libs/WindowManager/Shell/res/values-ne/strings_tv.xml index 684d11490be3..d33fed67efb6 100644 --- a/libs/WindowManager/Shell/res/values-ne/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-ne/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"PIP लाई बन्द गर्नुहोस्"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"फुल स्क्रिन"</string> <string name="pip_move" msgid="1544227837964635439">"PIP सार्नुहोस्"</string> + <string name="pip_expand" msgid="7605396312689038178">"PIP विन्डो एक्स्पान्ड गर्नु…"</string> + <string name="pip_collapse" msgid="5732233773786896094">"PIP विन्डो कोल्याप्स गर्नुहोस्"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" कन्ट्रोल मेनु खोल्न "<annotation icon="home_icon">" होम "</annotation>" बटन दुई पटक थिच्नुहोस्"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-nl/strings.xml b/libs/WindowManager/Shell/res/values-nl/strings.xml index 428cb3fb65d7..8468b04c66da 100644 --- a/libs/WindowManager/Shell/res/values-nl/strings.xml +++ b/libs/WindowManager/Shell/res/values-nl/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Cameraproblemen?\nTik om opnieuw passend te maken."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Is dit geen oplossing?\nTik om terug te zetten."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Geen cameraproblemen? Tik om te sluiten."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Sommige apps werken het best in de staande stand"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Probeer een van deze opties om optimaal gebruik te maken van je ruimte"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Draai je apparaat om naar volledig scherm te schakelen"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Dubbeltik naast een app om deze opnieuw te positioneren"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-nl/strings_tv.xml b/libs/WindowManager/Shell/res/values-nl/strings_tv.xml index 8562517bd58b..9763c5665ab2 100644 --- a/libs/WindowManager/Shell/res/values-nl/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-nl/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"PIP sluiten"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Volledig scherm"</string> <string name="pip_move" msgid="1544227837964635439">"SIS verplaatsen"</string> + <string name="pip_expand" msgid="7605396312689038178">"SIS uitvouwen"</string> + <string name="pip_collapse" msgid="5732233773786896094">"SIS samenvouwen"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Druk twee keer op "<annotation icon="home_icon">" HOME "</annotation>" voor bedieningselementen"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-or/strings.xml b/libs/WindowManager/Shell/res/values-or/strings.xml index f9668a1112b3..a8d8448edf99 100644 --- a/libs/WindowManager/Shell/res/values-or/strings.xml +++ b/libs/WindowManager/Shell/res/values-or/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"କ୍ୟାମେରାରେ ସମସ୍ୟା ଅଛି?\nପୁଣି ଫିଟ କରିବାକୁ ଟାପ କରନ୍ତୁ"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"ଏହାର ସମାଧାନ ହୋଇନାହିଁ?\nଫେରିଯିବା ପାଇଁ ଟାପ କରନ୍ତୁ"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"କ୍ୟାମେରାରେ କିଛି ସମସ୍ୟା ନାହିଁ? ଖାରଜ କରିବାକୁ ଟାପ କରନ୍ତୁ।"</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"କିଛି ଆପ ପୋର୍ଟ୍ରେଟରେ ସବୁଠାରୁ ଭଲ କାମ କରେ"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"ଆପଣଙ୍କ ସ୍ପେସରୁ ଅଧିକ ଲାଭ ପାଇବାକୁ ଏହି ବିକଳ୍ପଗୁଡ଼ିକ ମଧ୍ୟରୁ ଗୋଟିଏ ବ୍ୟବହାର କରି ଦେଖନ୍ତୁ"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"ପୂର୍ଣ୍ଣ-ସ୍କ୍ରିନ ବ୍ୟବହାର କରିବାକୁ ଆପଣଙ୍କ ଡିଭାଇସକୁ ରୋଟେଟ କରନ୍ତୁ"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"ଏକ ଆପକୁ ରିପୋଜିସନ କରିବା ପାଇଁ ଏହା ପାଖରେ ଦୁଇଥର-ଟାପ କରନ୍ତୁ"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"ବୁଝିଗଲି"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-or/strings_tv.xml b/libs/WindowManager/Shell/res/values-or/strings_tv.xml index f8bc01642d88..e0344855bd1f 100644 --- a/libs/WindowManager/Shell/res/values-or/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-or/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"PIP ବନ୍ଦ କରନ୍ତୁ"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"ପୂର୍ଣ୍ଣ ସ୍କ୍ରୀନ୍"</string> <string name="pip_move" msgid="1544227837964635439">"PIPକୁ ମୁଭ କରନ୍ତୁ"</string> + <string name="pip_expand" msgid="7605396312689038178">"PIPକୁ ବିସ୍ତାର କରନ୍ତୁ"</string> + <string name="pip_collapse" msgid="5732233773786896094">"PIPକୁ ସଙ୍କୁଚିତ କରନ୍ତୁ"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ ପାଇଁ "<annotation icon="home_icon">" ହୋମ ବଟନ "</annotation>"କୁ ଦୁଇଥର ଦବାନ୍ତୁ"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-pa/strings.xml b/libs/WindowManager/Shell/res/values-pa/strings.xml index 7132597d5b11..f99176cb682d 100644 --- a/libs/WindowManager/Shell/res/values-pa/strings.xml +++ b/libs/WindowManager/Shell/res/values-pa/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"ਕੀ ਕੈਮਰੇ ਸੰਬੰਧੀ ਸਮੱਸਿਆਵਾਂ ਹਨ?\nਮੁੜ-ਫਿੱਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"ਕੀ ਇਹ ਠੀਕ ਨਹੀਂ ਹੋਈ?\nਵਾਪਸ ਉਹੀ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"ਕੀ ਕੈਮਰੇ ਸੰਬੰਧੀ ਕੋਈ ਸਮੱਸਿਆ ਨਹੀਂ ਹੈ? ਖਾਰਜ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"ਕੁਝ ਐਪਾਂ ਪੋਰਟਰੇਟ ਵਿੱਚ ਬਿਹਤਰ ਕੰਮ ਕਰਦੀਆਂ ਹਨ"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"ਆਪਣੀ ਜਗ੍ਹਾ ਦਾ ਵੱਧ ਤੋਂ ਵੱਧ ਲਾਹਾ ਲੈਣ ਲਈ ਇਨ੍ਹਾਂ ਵਿਕਲਪਾਂ ਵਿੱਚੋਂ ਕੋਈ ਇੱਕ ਵਰਤ ਕੇ ਦੇਖੋ"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"ਪੂਰੀ-ਸਕ੍ਰੀਨ ਮੋਡ \'ਤੇ ਜਾਣ ਲਈ ਆਪਣੇ ਡੀਵਾਈਸ ਨੂੰ ਘੁਮਾਓ"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"ਕਿਸੇ ਐਪ ਦੀ ਜਗ੍ਹਾ ਬਦਲਣ ਲਈ ਉਸ ਦੇ ਅੱਗੇ ਡਬਲ ਟੈਪ ਕਰੋ"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"ਸਮਝ ਲਿਆ"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-pa/strings_tv.xml b/libs/WindowManager/Shell/res/values-pa/strings_tv.xml index 1667e5fc6eac..9c01ac3f3cc0 100644 --- a/libs/WindowManager/Shell/res/values-pa/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-pa/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"PIP ਬੰਦ ਕਰੋ"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"ਪੂਰੀ ਸਕ੍ਰੀਨ"</string> <string name="pip_move" msgid="1544227837964635439">"PIP ਨੂੰ ਲਿਜਾਓ"</string> + <string name="pip_expand" msgid="7605396312689038178">"PIP ਦਾ ਵਿਸਤਾਰ ਕਰੋ"</string> + <string name="pip_collapse" msgid="5732233773786896094">"PIP ਨੂੰ ਸਮੇਟੋ"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" ਕੰਟਰੋਲਾਂ ਲਈ "<annotation icon="home_icon">" ਹੋਮ ਬਟਨ "</annotation>" ਨੂੰ ਦੋ ਵਾਰ ਦਬਾਓ"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-pl/strings.xml b/libs/WindowManager/Shell/res/values-pl/strings.xml index f7f97efa1a88..f2147c04d335 100644 --- a/libs/WindowManager/Shell/res/values-pl/strings.xml +++ b/libs/WindowManager/Shell/res/values-pl/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problemy z aparatem?\nKliknij, aby dopasować"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Naprawa się nie udała?\nKliknij, aby cofnąć"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Brak problemów z aparatem? Kliknij, aby zamknąć"</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Niektóre aplikacje działają najlepiej w orientacji pionowej"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Wypróbuj jedną z tych opcji, aby jak najlepiej wykorzystać miejsce"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Obróć urządzenie, aby przejść do pełnego ekranu"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Kliknij dwukrotnie obok aplikacji, aby ją przenieść"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-pl/strings_tv.xml b/libs/WindowManager/Shell/res/values-pl/strings_tv.xml index 28bf66a7ee1b..b922e2d5a6ba 100644 --- a/libs/WindowManager/Shell/res/values-pl/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-pl/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Zamknij PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Pełny ekran"</string> <string name="pip_move" msgid="1544227837964635439">"Przenieś PIP"</string> + <string name="pip_expand" msgid="7605396312689038178">"Rozwiń PIP"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Zwiń PIP"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Naciśnij dwukrotnie "<annotation icon="home_icon">"EKRAN GŁÓWNY"</annotation>", aby wyświetlić ustawienia"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml index a3d2ab0feffa..2efc5543dd87 100644 --- a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml +++ b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problemas com a câmera?\nToque para ajustar o enquadramento"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"O problema não foi corrigido?\nToque para reverter"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Não tem problemas com a câmera? Toque para dispensar."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Alguns apps funcionam melhor em modo retrato"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Tente uma destas opções para aproveitar seu espaço ao máximo"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Gire o dispositivo para entrar no modo de tela cheia"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Toque duas vezes ao lado de um app para reposicionar"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Entendi"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-pt-rBR/strings_tv.xml b/libs/WindowManager/Shell/res/values-pt-rBR/strings_tv.xml index 27626b8ecfd6..cc4eb3c32c1f 100644 --- a/libs/WindowManager/Shell/res/values-pt-rBR/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-pt-rBR/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Fechar PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Tela cheia"</string> <string name="pip_move" msgid="1544227837964635439">"Mover picture-in-picture"</string> + <string name="pip_expand" msgid="7605396312689038178">"Abrir picture-in-picture"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Fechar picture-in-picture"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Pressione o botão "<annotation icon="home_icon">"home"</annotation>" duas vezes para acessar os controles"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml index 86872c811857..c68a6934dead 100644 --- a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml +++ b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problemas com a câmara?\nToque aqui para reajustar"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Não foi corrigido?\nToque para reverter"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nenhum problema com a câmara? Toque para ignorar."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Algumas apps funcionam melhor no modo vertical"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Experimente uma destas opções para aproveitar ao máximo o seu espaço"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Rode o dispositivo para ficar em ecrã inteiro"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Toque duas vezes junto a uma app para a reposicionar"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-pt-rPT/strings_tv.xml b/libs/WindowManager/Shell/res/values-pt-rPT/strings_tv.xml index a2010cee9e03..c4ae78d89ba8 100644 --- a/libs/WindowManager/Shell/res/values-pt-rPT/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-pt-rPT/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Fechar PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Ecrã inteiro"</string> <string name="pip_move" msgid="1544227837964635439">"Mover Ecrã no ecrã"</string> + <string name="pip_expand" msgid="7605396312689038178">"Expandir Ecrã no ecrã"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Reduzir Ecrã no ecrã"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Prima duas vezes "<annotation icon="home_icon">" PÁGINA INICIAL "</annotation>" para controlos"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-pt/strings.xml b/libs/WindowManager/Shell/res/values-pt/strings.xml index a3d2ab0feffa..2efc5543dd87 100644 --- a/libs/WindowManager/Shell/res/values-pt/strings.xml +++ b/libs/WindowManager/Shell/res/values-pt/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problemas com a câmera?\nToque para ajustar o enquadramento"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"O problema não foi corrigido?\nToque para reverter"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Não tem problemas com a câmera? Toque para dispensar."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Alguns apps funcionam melhor em modo retrato"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Tente uma destas opções para aproveitar seu espaço ao máximo"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Gire o dispositivo para entrar no modo de tela cheia"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Toque duas vezes ao lado de um app para reposicionar"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Entendi"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-pt/strings_tv.xml b/libs/WindowManager/Shell/res/values-pt/strings_tv.xml index 27626b8ecfd6..cc4eb3c32c1f 100644 --- a/libs/WindowManager/Shell/res/values-pt/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-pt/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Fechar PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Tela cheia"</string> <string name="pip_move" msgid="1544227837964635439">"Mover picture-in-picture"</string> + <string name="pip_expand" msgid="7605396312689038178">"Abrir picture-in-picture"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Fechar picture-in-picture"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Pressione o botão "<annotation icon="home_icon">"home"</annotation>" duas vezes para acessar os controles"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ro/strings.xml b/libs/WindowManager/Shell/res/values-ro/strings.xml index 5448e459a268..804d34f980ff 100644 --- a/libs/WindowManager/Shell/res/values-ro/strings.xml +++ b/libs/WindowManager/Shell/res/values-ro/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Aveți probleme cu camera foto?\nAtingeți pentru a reîncadra"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Nu ați remediat problema?\nAtingeți pentru a reveni"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nu aveți probleme cu camera foto? Atingeți pentru a închide."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Unele aplicații funcționează cel mai bine în orientarea portret"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Încercați una dintre aceste opțiuni pentru a profita din plin de spațiu"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Rotiți dispozitivul pentru a trece în modul ecran complet"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Atingeți de două ori lângă o aplicație pentru a o repoziționa"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ro/strings_tv.xml b/libs/WindowManager/Shell/res/values-ro/strings_tv.xml index 18e29a60191f..86a30f49df15 100644 --- a/libs/WindowManager/Shell/res/values-ro/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-ro/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Închideți PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Ecran complet"</string> <string name="pip_move" msgid="1544227837964635439">"Mutați fereastra PIP"</string> + <string name="pip_expand" msgid="7605396312689038178">"Extindeți fereastra PIP"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Restrângeți fereastra PIP"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Apăsați de două ori "<annotation icon="home_icon">"butonul ecran de pornire"</annotation>" pentru comenzi"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ru/strings.xml b/libs/WindowManager/Shell/res/values-ru/strings.xml index 64e74a27d32b..95bf1cf11435 100644 --- a/libs/WindowManager/Shell/res/values-ru/strings.xml +++ b/libs/WindowManager/Shell/res/values-ru/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Проблемы с камерой?\nНажмите, чтобы исправить."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Не помогло?\nНажмите, чтобы отменить изменения."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Нет проблем с камерой? Нажмите, чтобы закрыть."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Некоторые приложения лучше работают в вертикальном режиме"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Чтобы эффективно использовать экранное пространство, выполните одно из следующих действий:"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Чтобы перейти в полноэкранный режим, поверните устройство."</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Чтобы переместить приложение, нажмите на него дважды."</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"ОК"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ru/strings_tv.xml b/libs/WindowManager/Shell/res/values-ru/strings_tv.xml index d119240adc4d..08623e1e69c5 100644 --- a/libs/WindowManager/Shell/res/values-ru/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-ru/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"\"Кадр в кадре\" – выйти"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Во весь экран"</string> <string name="pip_move" msgid="1544227837964635439">"Переместить PIP"</string> + <string name="pip_expand" msgid="7605396312689038178">"Развернуть PIP"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Свернуть PIP"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Элементы управления: дважды нажмите "<annotation icon="home_icon">" кнопку главного экрана "</annotation></string> </resources> diff --git a/libs/WindowManager/Shell/res/values-si/strings.xml b/libs/WindowManager/Shell/res/values-si/strings.xml index 3cdaa72b0153..23dd65ad7b31 100644 --- a/libs/WindowManager/Shell/res/values-si/strings.xml +++ b/libs/WindowManager/Shell/res/values-si/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"කැමරා ගැටලුද?\nයළි සවි කිරීමට තට්ටු කරන්න"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"එය විසඳුවේ නැතිද?\nප්රතිවර්තනය කිරීමට තට්ටු කරන්න"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"කැමරා ගැටලු නොමැතිද? ඉවත දැමීමට තට්ටු කරන්න"</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"සමහර යෙදුම් ප්රතිමූර්තිය තුළ හොඳින්ම ක්රියා කරයි"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"ඔබගේ ඉඩෙන් උපරිම ප්රයෝජන ගැනීමට මෙම විකල්පවලින් එකක් උත්සාහ කරන්න"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"සම්පූර්ණ තිරයට යාමට ඔබගේ උපාංගය කරකවන්න"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"එය නැවත ස්ථානගත කිරීමට යෙදුමකට යාබදව දෙවරක් තට්ටු කරන්න"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"තේරුණා"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-si/strings_tv.xml b/libs/WindowManager/Shell/res/values-si/strings_tv.xml index 86769b6ee849..fbb0ebba0623 100644 --- a/libs/WindowManager/Shell/res/values-si/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-si/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"PIP වසන්න"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"සම්පූර්ණ තිරය"</string> <string name="pip_move" msgid="1544227837964635439">"PIP ගෙන යන්න"</string> + <string name="pip_expand" msgid="7605396312689038178">"PIP දිග හරින්න"</string> + <string name="pip_collapse" msgid="5732233773786896094">"PIP හකුළන්න"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" පාලන සඳහා "<annotation icon="home_icon">" මුල් පිටුව "</annotation>" දෙවරක් ඔබන්න"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-sk/strings.xml b/libs/WindowManager/Shell/res/values-sk/strings.xml index daa202175622..a231cacefb20 100644 --- a/libs/WindowManager/Shell/res/values-sk/strings.xml +++ b/libs/WindowManager/Shell/res/values-sk/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problémy s kamerou?\nKlepnutím znova upravte."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Nevyriešilo sa to?\nKlepnutím sa vráťte."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nemáte problémy s kamerou? Klepnutím zatvoríte."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Niektoré aplikácie fungujú najlepšie v režime na výšku"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Vyskúšajte jednu z týchto možností a využívajte svoj priestor naplno"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Otočením zariadenia prejdete do režimu celej obrazovky"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Dvojitým klepnutím vedľa aplikácie zmeníte jej pozíciu"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Dobre"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-sk/strings_tv.xml b/libs/WindowManager/Shell/res/values-sk/strings_tv.xml index 6f6ccb703cf6..81cb0eafc759 100644 --- a/libs/WindowManager/Shell/res/values-sk/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-sk/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Zavrieť režim PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Celá obrazovka"</string> <string name="pip_move" msgid="1544227837964635439">"Presunúť obraz v obraze"</string> + <string name="pip_expand" msgid="7605396312689038178">"Rozbaliť obraz v obraze"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Zbaliť obraz v obraze"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Ovládanie zobraz. dvoj. stlač. "<annotation icon="home_icon">" TLAČIDLA PLOCHY "</annotation></string> </resources> diff --git a/libs/WindowManager/Shell/res/values-sl/strings.xml b/libs/WindowManager/Shell/res/values-sl/strings.xml index b4c7b951d14a..adeaae978eaa 100644 --- a/libs/WindowManager/Shell/res/values-sl/strings.xml +++ b/libs/WindowManager/Shell/res/values-sl/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Težave s fotoaparatom?\nDotaknite se za vnovično prilagoditev"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"To ni odpravilo težave?\nDotaknite se za povrnitev"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nimate težav s fotoaparatom? Dotaknite se za opustitev."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Nekatere aplikacije najbolje delujejo v navpični postavitvi"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Poskusite eno od teh možnosti za čim boljši izkoristek prostora"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Če želite preklopiti v celozaslonski način, zasukajte napravo."</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Dvakrat se dotaknite ob aplikaciji, če jo želite prestaviti."</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"V redu"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-sl/strings_tv.xml b/libs/WindowManager/Shell/res/values-sl/strings_tv.xml index 837794ad4be7..060aaa0ce647 100644 --- a/libs/WindowManager/Shell/res/values-sl/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-sl/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Zapri način PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Celozaslonsko"</string> <string name="pip_move" msgid="1544227837964635439">"Premakni sliko v sliki"</string> + <string name="pip_expand" msgid="7605396312689038178">"Razširi sliko v sliki"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Strni sliko v sliki"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Za kontrolnike dvakrat pritisnite gumb za "<annotation icon="home_icon">" ZAČETNI ZASLON "</annotation></string> </resources> diff --git a/libs/WindowManager/Shell/res/values-sq/strings.xml b/libs/WindowManager/Shell/res/values-sq/strings.xml index 5051351bf340..2839b4bae7e4 100644 --- a/libs/WindowManager/Shell/res/values-sq/strings.xml +++ b/libs/WindowManager/Shell/res/values-sq/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Ka probleme me kamerën?\nTrokit për ta ripërshtatur"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Nuk u rregullua?\nTrokit për ta rikthyer"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nuk ka probleme me kamerën? Trokit për ta shpërfillur."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Disa aplikacione funksionojnë më mirë në modalitetin vertikal"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Provo një nga këto opsione për ta shfrytëzuar sa më mirë hapësirën"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Rrotullo ekranin për të kaluar në ekran të plotë"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Trokit dy herë pranë një aplikacioni për ta ripozicionuar"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"E kuptova"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-sq/strings_tv.xml b/libs/WindowManager/Shell/res/values-sq/strings_tv.xml index 107870d0489f..9bfdb6a3edd8 100644 --- a/libs/WindowManager/Shell/res/values-sq/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-sq/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Mbyll PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Ekrani i plotë"</string> <string name="pip_move" msgid="1544227837964635439">"Zhvendos PIP"</string> + <string name="pip_expand" msgid="7605396312689038178">"Zgjero PIP"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Palos PIP"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Trokit dy herë "<annotation icon="home_icon">" KREU "</annotation>" për kontrollet"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-sr/strings.xml b/libs/WindowManager/Shell/res/values-sr/strings.xml index 96bb48a76368..9db6b7c63610 100644 --- a/libs/WindowManager/Shell/res/values-sr/strings.xml +++ b/libs/WindowManager/Shell/res/values-sr/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Имате проблема са камером?\nДодирните да бисте поново уклопили"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Проблем није решен?\nДодирните да бисте вратили"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Немате проблема са камером? Додирните да бисте одбацили."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Неке апликације најбоље функционишу у усправном режиму"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Испробајте једну од ових опција да бисте на најбољи начин искористили простор"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Ротирајте уређај за приказ преко целог екрана"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Двапут додирните поред апликације да бисте променили њену позицију"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Важи"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-sr/strings_tv.xml b/libs/WindowManager/Shell/res/values-sr/strings_tv.xml index ee5690ba4a9a..6bc5c87bab48 100644 --- a/libs/WindowManager/Shell/res/values-sr/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-sr/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Затвори PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Цео екран"</string> <string name="pip_move" msgid="1544227837964635439">"Премести слику у слици"</string> + <string name="pip_expand" msgid="7605396312689038178">"Прошири слику у слици"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Скупи слику у слици"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Двапут притисните "<annotation icon="home_icon">" HOME "</annotation>" за контроле"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-sv/strings.xml b/libs/WindowManager/Shell/res/values-sv/strings.xml index 9fa5c19e3dd4..f6bd55423cdc 100644 --- a/libs/WindowManager/Shell/res/values-sv/strings.xml +++ b/libs/WindowManager/Shell/res/values-sv/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problem med kameran?\nTryck för att anpassa på nytt"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Löstes inte problemet?\nTryck för att återställa"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Inga problem med kameran? Tryck för att ignorera."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Vissa appar fungerar bäst i stående läge"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Testa med ett av dessa alternativ för att få ut mest möjliga av ytan"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Rotera skärmen för att gå över till helskärmsläge"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Tryck snabbt två gånger bredvid en app för att flytta den"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-sv/strings_tv.xml b/libs/WindowManager/Shell/res/values-sv/strings_tv.xml index 7355adf51e97..b3465ab1db85 100644 --- a/libs/WindowManager/Shell/res/values-sv/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-sv/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Stäng PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Helskärm"</string> <string name="pip_move" msgid="1544227837964635439">"Flytta BIB"</string> + <string name="pip_expand" msgid="7605396312689038178">"Utöka bild-i-bild"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Komprimera bild-i-bild"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Tryck snabbt två gånger på "<annotation icon="home_icon">" HEM "</annotation>" för kontroller"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-sw/strings.xml b/libs/WindowManager/Shell/res/values-sw/strings.xml index 8c026f96392d..f6e558527ee5 100644 --- a/libs/WindowManager/Shell/res/values-sw/strings.xml +++ b/libs/WindowManager/Shell/res/values-sw/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Je, kuna hitilafu za kamera?\nGusa ili urekebishe"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Umeshindwa kurekebisha?\nGusa ili urejeshe nakala ya awali"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Je, hakuna hitilafu za kamera? Gusa ili uondoe."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Baadhi ya programu hufanya kazi vizuri zaidi zikiwa wima"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Jaribu moja kati ya chaguo hizi ili utumie nafasi ya skrini yako kwa ufanisi"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Zungusha kifaa chako ili uende kwenye hali ya skrini nzima"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Gusa mara mbili karibu na programu ili uihamishe"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Nimeelewa"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-sw/strings_tv.xml b/libs/WindowManager/Shell/res/values-sw/strings_tv.xml index 0ee28416137a..baff49ed821a 100644 --- a/libs/WindowManager/Shell/res/values-sw/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-sw/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Funga PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Skrini nzima"</string> <string name="pip_move" msgid="1544227837964635439">"Kuhamisha PIP"</string> + <string name="pip_expand" msgid="7605396312689038178">"Panua PIP"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Kunja PIP"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Bonyeza mara mbili kitufe cha "<annotation icon="home_icon">" UKURASA WA KWANZA "</annotation>" kupata vidhibiti"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ta/strings.xml b/libs/WindowManager/Shell/res/values-ta/strings.xml index cb3d138035b2..d8334adfe5ef 100644 --- a/libs/WindowManager/Shell/res/values-ta/strings.xml +++ b/libs/WindowManager/Shell/res/values-ta/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"கேமரா தொடர்பான சிக்கல்களா?\nமீண்டும் பொருத்த தட்டவும்"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"சிக்கல்கள் சரிசெய்யப்படவில்லையா?\nமாற்றியமைக்க தட்டவும்"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"கேமரா தொடர்பான சிக்கல்கள் எதுவும் இல்லையா? நிராகரிக்க தட்டவும்."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"சில ஆப்ஸ் \'போர்ட்ரெய்ட்டில்\' சிறப்பாகச் செயல்படும்"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"ஸ்பேஸ்களிலிருந்து அதிகப் பலன்களைப் பெற இந்த விருப்பங்களில் ஒன்றைப் பயன்படுத்துங்கள்"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"முழுத்திரைக்குச் செல்ல உங்கள் சாதனத்தைச் சுழற்றவும்"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"ஆப்ஸை இடம் மாற்ற, ஆப்ஸுக்கு அடுத்து இருமுறை தட்டவும்"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"சரி"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ta/strings_tv.xml b/libs/WindowManager/Shell/res/values-ta/strings_tv.xml index 8bcc43bea59a..4439e299c919 100644 --- a/libs/WindowManager/Shell/res/values-ta/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-ta/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"PIPஐ மூடு"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"முழுத்திரை"</string> <string name="pip_move" msgid="1544227837964635439">"PIPபை நகர்த்து"</string> + <string name="pip_expand" msgid="7605396312689038178">"PIPபை விரிவாக்கு"</string> + <string name="pip_collapse" msgid="5732233773786896094">"PIPபைச் சுருக்கு"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" கட்டுப்பாடுகள்: "<annotation icon="home_icon">" முகப்பு "</annotation>" பட்டனை இருமுறை அழுத்துக"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-te/strings.xml b/libs/WindowManager/Shell/res/values-te/strings.xml index 7589e70cc681..733075550007 100644 --- a/libs/WindowManager/Shell/res/values-te/strings.xml +++ b/libs/WindowManager/Shell/res/values-te/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"కెమెరా సమస్యలు ఉన్నాయా?\nరీఫిట్ చేయడానికి ట్యాప్ చేయండి"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"దాని సమస్యను పరిష్కరించలేదా?\nపూర్వస్థితికి మార్చడానికి ట్యాప్ చేయండి"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"కెమెరా సమస్యలు లేవా? తీసివేయడానికి ట్యాప్ చేయండి."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"కొన్ని యాప్లు పోర్ట్రెయిట్లో ఉత్తమంగా పని చేస్తాయి"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"మీ ప్రదేశాన్ని ఎక్కువగా ఉపయోగించుకోవడానికి ఈ ఆప్షన్లలో ఒకదాన్ని ట్రై చేయండి"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"ఫుల్ స్క్రీన్కు వెళ్లడానికి మీ పరికరాన్ని తిప్పండి"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"యాప్ స్థానాన్ని మార్చడానికి దాని పక్కన డబుల్-ట్యాప్ చేయండి"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"అర్థమైంది"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-te/strings_tv.xml b/libs/WindowManager/Shell/res/values-te/strings_tv.xml index 6e80bd7b3a0c..35579346615f 100644 --- a/libs/WindowManager/Shell/res/values-te/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-te/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"PIPని మూసివేయి"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"ఫుల్-స్క్రీన్"</string> <string name="pip_move" msgid="1544227837964635439">"PIPను తరలించండి"</string> + <string name="pip_expand" msgid="7605396312689038178">"PIPని విస్తరించండి"</string> + <string name="pip_collapse" msgid="5732233773786896094">"PIPని కుదించండి"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" కంట్రోల్స్ కోసం "<annotation icon="home_icon">" HOME "</annotation>" బటన్ రెండుసార్లు నొక్కండి"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-th/strings.xml b/libs/WindowManager/Shell/res/values-th/strings.xml index d8a33ff4c8e5..cfee8ea3242e 100644 --- a/libs/WindowManager/Shell/res/values-th/strings.xml +++ b/libs/WindowManager/Shell/res/values-th/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"หากพบปัญหากับกล้อง\nแตะเพื่อแก้ไข"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"หากไม่ได้แก้ไข\nแตะเพื่อเปลี่ยนกลับ"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"หากไม่พบปัญหากับกล้อง แตะเพื่อปิด"</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"บางแอปทำงานได้ดีที่สุดในแนวตั้ง"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"ลองใช้หนึ่งในตัวเลือกเหล่านี้เพื่อให้ได้ประโยชน์สูงสุดจากพื้นที่ว่าง"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"หมุนอุปกรณ์ให้แสดงเต็มหน้าจอ"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"แตะสองครั้งข้างแอปเพื่อเปลี่ยนตำแหน่ง"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"รับทราบ"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-th/strings_tv.xml b/libs/WindowManager/Shell/res/values-th/strings_tv.xml index b6f63699cc00..0a07d157ec6f 100644 --- a/libs/WindowManager/Shell/res/values-th/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-th/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"ปิด PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"เต็มหน้าจอ"</string> <string name="pip_move" msgid="1544227837964635439">"ย้าย PIP"</string> + <string name="pip_expand" msgid="7605396312689038178">"ขยาย PIP"</string> + <string name="pip_collapse" msgid="5732233773786896094">"ยุบ PIP"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" กดปุ่ม "<annotation icon="home_icon">" หน้าแรก "</annotation>" สองครั้งเพื่อเปิดการควบคุม"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-tl/strings.xml b/libs/WindowManager/Shell/res/values-tl/strings.xml index 35a58b33931d..eed624dd5069 100644 --- a/libs/WindowManager/Shell/res/values-tl/strings.xml +++ b/libs/WindowManager/Shell/res/values-tl/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"May mga isyu sa camera?\nI-tap para i-refit"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Hindi ito naayos?\nI-tap para i-revert"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Walang isyu sa camera? I-tap para i-dismiss."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"May ilang app na pinakamainam gamitin nang naka-portrait"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Subukan ang isa sa mga opsyong ito para masulit ang iyong space"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"I-rotate ang iyong device para mag-full screen"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Mag-double tap sa tabi ng isang app para iposisyon ito ulit"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-tl/strings_tv.xml b/libs/WindowManager/Shell/res/values-tl/strings_tv.xml index 71ca2306ea03..9a11a38fa492 100644 --- a/libs/WindowManager/Shell/res/values-tl/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-tl/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Isara ang PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Full screen"</string> <string name="pip_move" msgid="1544227837964635439">"Ilipat ang PIP"</string> + <string name="pip_expand" msgid="7605396312689038178">"I-expand ang PIP"</string> + <string name="pip_collapse" msgid="5732233773786896094">"I-collapse ang PIP"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" I-double press ang "<annotation icon="home_icon">" HOME "</annotation>" para sa mga kontrol"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-tr/strings.xml b/libs/WindowManager/Shell/res/values-tr/strings.xml index 8a9fb7546a20..2b4a2d0550f0 100644 --- a/libs/WindowManager/Shell/res/values-tr/strings.xml +++ b/libs/WindowManager/Shell/res/values-tr/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Kameranızda sorun mu var?\nDüzeltmek için dokunun"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Bu işlem sorunu düzeltmedi mi?\nİşlemi geri almak için dokunun"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Kameranızda sorun yok mu? Kapatmak için dokunun."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Bazı uygulamalar dikey modda en iyi performansı gösterir"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Alanınızı en verimli şekilde kullanmak için bu seçeneklerden birini deneyin"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Tam ekrana geçmek için cihazınızı döndürün"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Yeniden konumlandırmak için uygulamanın yanına iki kez dokunun"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Anladım"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-tr/strings_tv.xml b/libs/WindowManager/Shell/res/values-tr/strings_tv.xml index e6ae7f167758..bf4bc6f1fff7 100644 --- a/libs/WindowManager/Shell/res/values-tr/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-tr/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"PIP\'yi kapat"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Tam ekran"</string> <string name="pip_move" msgid="1544227837964635439">"PIP\'yi taşı"</string> + <string name="pip_expand" msgid="7605396312689038178">"PIP penceresini genişlet"</string> + <string name="pip_collapse" msgid="5732233773786896094">"PIP penceresini daralt"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Kontroller için "<annotation icon="home_icon">" ANA SAYFA "</annotation>"\'ya iki kez basın"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-uk/strings.xml b/libs/WindowManager/Shell/res/values-uk/strings.xml index aac9031a7ca7..c3411a837c78 100644 --- a/libs/WindowManager/Shell/res/values-uk/strings.xml +++ b/libs/WindowManager/Shell/res/values-uk/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Проблеми з камерою?\nНатисніть, щоб пристосувати"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Проблему не вирішено?\nНатисніть, щоб скасувати зміни"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Немає проблем із камерою? Торкніться, щоб закрити."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Деякі додатки найкраще працюють у вертикальній орієнтації"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Щоб максимально ефективно використовувати місце на екрані, спробуйте виконати одну з наведених нижче дій"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Щоб перейти в повноекранний режим, поверніть пристрій"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Щоб перемістити додаток, двічі торкніться області поруч із ним"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"ОK"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-uk/strings_tv.xml b/libs/WindowManager/Shell/res/values-uk/strings_tv.xml index 97e1f09844fa..7e9f54e68f54 100644 --- a/libs/WindowManager/Shell/res/values-uk/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-uk/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Закрити PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"На весь екран"</string> <string name="pip_move" msgid="1544227837964635439">"Перемістити картинку в картинці"</string> + <string name="pip_expand" msgid="7605396312689038178">"Розгорнути картинку в картинці"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Згорнути картинку в картинці"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Відкрити елементи керування: двічі натисніть "<annotation icon="home_icon">"HOME"</annotation></string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ur/strings.xml b/libs/WindowManager/Shell/res/values-ur/strings.xml index e3bab32f309d..a31c2be25643 100644 --- a/libs/WindowManager/Shell/res/values-ur/strings.xml +++ b/libs/WindowManager/Shell/res/values-ur/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"کیمرے کے مسائل؟\nدوبارہ فٹ کرنے کیلئے تھپتھپائیں"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"یہ حل نہیں ہوا؟\nلوٹانے کیلئے تھپتھپائیں"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"کوئی کیمرے کا مسئلہ نہیں ہے؟ برخاست کرنے کیلئے تھپتھپائیں۔"</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"کچھ ایپس پورٹریٹ میں بہترین کام کرتی ہیں"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"اپنی اسپیس کا زیادہ سے زیادہ فائدہ اٹھانے کے لیے ان اختیارات میں سے ایک کو آزمائیں"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"پوری اسکرین پر جانے کیلئے اپنا آلہ گھمائیں"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"کسی ایپ کی پوزیشن تبدیل کرنے کے لیے اس کے آگے دو بار تھپتھپائیں"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"سمجھ آ گئی"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ur/strings_tv.xml b/libs/WindowManager/Shell/res/values-ur/strings_tv.xml index 1418570f2538..c2ef69ff1488 100644 --- a/libs/WindowManager/Shell/res/values-ur/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-ur/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"PIP بند کریں"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"فُل اسکرین"</string> <string name="pip_move" msgid="1544227837964635439">"PIP کو منتقل کریں"</string> + <string name="pip_expand" msgid="7605396312689038178">"PIP کو پھیلائیں"</string> + <string name="pip_collapse" msgid="5732233773786896094">"PIP کو سکیڑیں"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" کنٹرولز کے لیے "<annotation icon="home_icon">"ہوم "</annotation>" بٹن کو دو بار دبائیں"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-uz/strings.xml b/libs/WindowManager/Shell/res/values-uz/strings.xml index 54ec89ae6b30..2e3222560dde 100644 --- a/libs/WindowManager/Shell/res/values-uz/strings.xml +++ b/libs/WindowManager/Shell/res/values-uz/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Kamera nosozmi?\nQayta moslash uchun bosing"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Tuzatilmadimi?\nQaytarish uchun bosing"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Kamera muammosizmi? Yopish uchun bosing."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Ayrim ilovalar tik holatda ishlashga eng mos"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Muhitdan yanada samarali foydalanish uchun quyidagilardan birini sinang"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Butun ekranda ochish uchun qurilmani buring"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Qayta joylash uchun keyingi ilova ustiga ikki marta bosing"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-uz/strings_tv.xml b/libs/WindowManager/Shell/res/values-uz/strings_tv.xml index 31c762ef5f64..9ab95c80aa25 100644 --- a/libs/WindowManager/Shell/res/values-uz/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-uz/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Kadr ichida kadr – chiqish"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Butun ekran"</string> <string name="pip_move" msgid="1544227837964635439">"PIPni siljitish"</string> + <string name="pip_expand" msgid="7605396312689038178">"PIP funksiyasini yoyish"</string> + <string name="pip_collapse" msgid="5732233773786896094">"PIP funksiyasini yopish"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Boshqaruv uchun "<annotation icon="home_icon">"ASOSIY"</annotation>" tugmani ikki marta bosing"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-vi/strings.xml b/libs/WindowManager/Shell/res/values-vi/strings.xml index b6837023ccb8..8f3cffecc952 100644 --- a/libs/WindowManager/Shell/res/values-vi/strings.xml +++ b/libs/WindowManager/Shell/res/values-vi/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Có vấn đề với máy ảnh?\nHãy nhấn để sửa lỗi"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Bạn chưa khắc phục vấn đề?\nHãy nhấn để hủy bỏ"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Không có vấn đề với máy ảnh? Hãy nhấn để đóng."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Một số ứng dụng hoạt động tốt nhất ở chế độ dọc"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Hãy thử một trong các tuỳ chọn sau để tận dụng không gian"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Xoay thiết bị để chuyển sang chế độ toàn màn hình"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Nhấn đúp vào bên cạnh ứng dụng để đặt lại vị trí"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-vi/strings_tv.xml b/libs/WindowManager/Shell/res/values-vi/strings_tv.xml index b46cd49c1901..146376d3cab6 100644 --- a/libs/WindowManager/Shell/res/values-vi/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-vi/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Đóng PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Toàn màn hình"</string> <string name="pip_move" msgid="1544227837964635439">"Di chuyển PIP (Ảnh trong ảnh)"</string> + <string name="pip_expand" msgid="7605396312689038178">"Mở rộng PIP (Ảnh trong ảnh)"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Thu gọn PIP (Ảnh trong ảnh)"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Nhấn đúp vào nút "<annotation icon="home_icon">" MÀN HÌNH CHÍNH "</annotation>" để mở trình đơn điều khiển"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml index 811d8602a499..19a9d371e435 100644 --- a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml +++ b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"相机有问题?\n点按即可整修"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"没有解决此问题?\n点按即可恢复"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"相机没有问题?点按即可忽略。"</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"某些应用在纵向模式下才能发挥最佳效果"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"这些选项都有助于您最大限度地利用屏幕空间,不妨从中择一试试"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"旋转设备即可进入全屏模式"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"在某个应用旁边连续点按两次,即可调整它的位置"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"知道了"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-zh-rCN/strings_tv.xml b/libs/WindowManager/Shell/res/values-zh-rCN/strings_tv.xml index b6fec635a470..55407d2c699d 100644 --- a/libs/WindowManager/Shell/res/values-zh-rCN/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-zh-rCN/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"关闭画中画"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"全屏"</string> <string name="pip_move" msgid="1544227837964635439">"移动画中画窗口"</string> + <string name="pip_expand" msgid="7605396312689038178">"展开 PIP"</string> + <string name="pip_collapse" msgid="5732233773786896094">"收起 PIP"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" 按两次"<annotation icon="home_icon">"主屏幕"</annotation>"按钮可查看相关控件"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml index 2a017148f7c4..0c40e963f2e4 100644 --- a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml +++ b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"相機有問題?\n輕按即可修正"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"未能修正問題?\n輕按即可還原"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"相機冇問題?㩒一下就可以即可閂咗佢。"</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"部分應用程式需要使用直向模式才能發揮最佳效果"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"請嘗試以下選項,充分運用螢幕的畫面空間"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"旋轉裝置方向即可進入全螢幕模式"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"在應用程式旁輕按兩下即可調整位置"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"知道了"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-zh-rHK/strings_tv.xml b/libs/WindowManager/Shell/res/values-zh-rHK/strings_tv.xml index b5d54cb04354..15e278d8ecc2 100644 --- a/libs/WindowManager/Shell/res/values-zh-rHK/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-zh-rHK/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"關閉 PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"全螢幕"</string> <string name="pip_move" msgid="1544227837964635439">"移動畫中畫"</string> + <string name="pip_expand" msgid="7605396312689038178">"展開畫中畫"</string> + <string name="pip_collapse" msgid="5732233773786896094">"收合畫中畫"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" 按兩下"<annotation icon="home_icon">" 主畫面按鈕"</annotation>"即可顯示控制項"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml index 292a43912668..8691352cf94a 100644 --- a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml +++ b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"相機有問題嗎?\n輕觸即可修正"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"未修正問題嗎?\n輕觸即可還原"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"相機沒問題嗎?輕觸即可關閉。"</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"某些應用程式在直向模式下才能發揮最佳效果"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"請試試這裡的任一方式,以充分運用螢幕畫面的空間"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"旋轉裝置方向即可進入全螢幕模式"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"在應用程式旁輕觸兩下即可調整位置"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"我知道了"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-zh-rTW/strings_tv.xml b/libs/WindowManager/Shell/res/values-zh-rTW/strings_tv.xml index 57db7a839ea2..0b17b31d23d0 100644 --- a/libs/WindowManager/Shell/res/values-zh-rTW/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-zh-rTW/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"關閉子母畫面"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"全螢幕"</string> <string name="pip_move" msgid="1544227837964635439">"移動子母畫面"</string> + <string name="pip_expand" msgid="7605396312689038178">"展開子母畫面"</string> + <string name="pip_collapse" msgid="5732233773786896094">"收合子母畫面"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" 按兩下"<annotation icon="home_icon">"主畫面按鈕"</annotation>"即可顯示控制選項"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-zu/strings.xml b/libs/WindowManager/Shell/res/values-zu/strings.xml index 389eb08bf154..44ffbc6afa45 100644 --- a/libs/WindowManager/Shell/res/values-zu/strings.xml +++ b/libs/WindowManager/Shell/res/values-zu/strings.xml @@ -76,13 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Izinkinga zekhamera?\nThepha ukuze uyilinganise kabusha"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Akuyilungisanga?\nThepha ukuze ubuyele"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Azikho izinkinga zekhamera? Thepha ukuze ucashise."</string> - <!-- no translation found for letterbox_education_dialog_title (6688664582871779215) --> - <skip /> - <!-- no translation found for letterbox_education_dialog_subtext (4853542518367719562) --> - <skip /> - <!-- no translation found for letterbox_education_screen_rotation_text (5085786687366339027) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (1068293354123934727) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="6688664582871779215">"Amanye ama-app asebenza ngcono uma eme ngobude"</string> + <string name="letterbox_education_dialog_subtext" msgid="4853542518367719562">"Zama enye yalezi zinketho ukuze usebenzise isikhala sakho ngokugcwele"</string> + <string name="letterbox_education_screen_rotation_text" msgid="5085786687366339027">"Zungezisa idivayisi yakho ukuze uye esikrinini esigcwele"</string> + <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Thepha kabili eduze kwe-app ukuze uyimise kabusha"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Ngiyezwa"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-zu/strings_tv.xml b/libs/WindowManager/Shell/res/values-zu/strings_tv.xml index 646a488e4c35..dad8c8128222 100644 --- a/libs/WindowManager/Shell/res/values-zu/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-zu/strings_tv.xml @@ -22,4 +22,7 @@ <string name="pip_close" msgid="9135220303720555525">"Vala i-PIP"</string> <string name="pip_fullscreen" msgid="7278047353591302554">"Iskrini esigcwele"</string> <string name="pip_move" msgid="1544227837964635439">"Hambisa i-PIP"</string> + <string name="pip_expand" msgid="7605396312689038178">"Nweba i-PIP"</string> + <string name="pip_collapse" msgid="5732233773786896094">"Goqa i-PIP"</string> + <string name="pip_edu_text" msgid="3672999496647508701">" Chofoza kabili "<annotation icon="home_icon">" IKHAYA"</annotation>" mayelana nezilawuli"</string> </resources> diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java index 62fb840d29d1..ecdccd7b1419 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java @@ -34,6 +34,7 @@ import com.android.wm.shell.pip.phone.PipTouchHandler; import com.android.wm.shell.recents.RecentTasksController; import com.android.wm.shell.splitscreen.SplitScreenController; import com.android.wm.shell.startingsurface.StartingWindowController; +import com.android.wm.shell.transition.DefaultMixedHandler; import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.unfold.UnfoldTransitionHandler; @@ -131,6 +132,13 @@ public class ShellInitImpl { if (Transitions.ENABLE_SHELL_TRANSITIONS) { mTransitions.register(mShellTaskOrganizer); mUnfoldTransitionHandler.ifPresent(UnfoldTransitionHandler::init); + if (mSplitScreenOptional.isPresent() && mPipTouchHandlerOptional.isPresent()) { + final DefaultMixedHandler mixedHandler = new DefaultMixedHandler(mTransitions, + mPipTouchHandlerOptional.get().getTransitionHandler(), + mSplitScreenOptional.get().getTransitionHandler()); + // Added at end so that it has highest priority. + mTransitions.addHandler(mixedHandler); + } } // TODO(b/181599115): This should really be the pip controller, but until we can provide the diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java index 31f0ef0192ae..b20caf4b46bb 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java @@ -439,6 +439,7 @@ public class ShellTaskOrganizer extends TaskOrganizer implements } notifyLocusVisibilityIfNeeded(info.getTaskInfo()); notifyCompatUI(info.getTaskInfo(), listener); + mRecentTasks.ifPresent(recentTasks -> recentTasks.onTaskAdded(info.getTaskInfo())); } /** 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 4ad08688bd51..24d500434c45 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 @@ -319,26 +319,27 @@ public abstract class WMShellBaseModule { @WMSingleton @Provides static Optional<FullscreenUnfoldController> provideFullscreenUnfoldController( - @DynamicOverride Optional<FullscreenUnfoldController> fullscreenUnfoldController, + @DynamicOverride Lazy<Optional<FullscreenUnfoldController>> fullscreenUnfoldController, Optional<ShellUnfoldProgressProvider> progressProvider) { if (progressProvider.isPresent() && progressProvider.get() != ShellUnfoldProgressProvider.NO_PROVIDER) { - return fullscreenUnfoldController; + return fullscreenUnfoldController.get(); } return Optional.empty(); } + @BindsOptionalOf + @DynamicOverride + abstract UnfoldTransitionHandler optionalUnfoldTransitionHandler(); + @WMSingleton @Provides static Optional<UnfoldTransitionHandler> provideUnfoldTransitionHandler( Optional<ShellUnfoldProgressProvider> progressProvider, - TransactionPool transactionPool, - Transitions transitions, - @ShellMainThread ShellExecutor executor) { - if (progressProvider.isPresent()) { - return Optional.of( - new UnfoldTransitionHandler(progressProvider.get(), transactionPool, executor, - transitions)); + @DynamicOverride Lazy<Optional<UnfoldTransitionHandler>> handler) { + if (progressProvider.isPresent() + && progressProvider.get() != ShellUnfoldProgressProvider.NO_PROVIDER) { + return handler.get(); } return Optional.empty(); } 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 e43f4fc34adf..96e5f60c952b 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 @@ -73,6 +73,8 @@ import com.android.wm.shell.splitscreen.StageTaskUnfoldController; import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.unfold.ShellUnfoldProgressProvider; import com.android.wm.shell.unfold.UnfoldBackgroundController; +import com.android.wm.shell.unfold.UnfoldTransitionHandler; +import com.android.wm.shell.unfold.animation.FullscreenUnfoldTaskAnimator; import java.util.Optional; @@ -349,15 +351,37 @@ public class WMShellModule { @Provides @DynamicOverride static FullscreenUnfoldController provideFullscreenUnfoldController( - Context context, Optional<ShellUnfoldProgressProvider> progressProvider, - Lazy<UnfoldBackgroundController> unfoldBackgroundController, - DisplayInsetsController displayInsetsController, + Optional<UnfoldTransitionHandler> unfoldTransitionHandler, + FullscreenUnfoldTaskAnimator fullscreenUnfoldTaskAnimator, + UnfoldBackgroundController unfoldBackgroundController, @ShellMainThread ShellExecutor mainExecutor ) { - return new FullscreenUnfoldController(context, mainExecutor, - unfoldBackgroundController.get(), progressProvider.get(), - displayInsetsController); + return new FullscreenUnfoldController(mainExecutor, + unfoldBackgroundController, progressProvider.get(), + unfoldTransitionHandler.get(), fullscreenUnfoldTaskAnimator); + } + + @Provides + static FullscreenUnfoldTaskAnimator provideFullscreenUnfoldTaskAnimator( + Context context, + DisplayInsetsController displayInsetsController + ) { + return new FullscreenUnfoldTaskAnimator(context, displayInsetsController); + } + + @WMSingleton + @Provides + @DynamicOverride + static UnfoldTransitionHandler provideUnfoldTransitionHandler( + Optional<ShellUnfoldProgressProvider> progressProvider, + FullscreenUnfoldTaskAnimator animator, + UnfoldBackgroundController backgroundController, + TransactionPool transactionPool, + Transitions transitions, + @ShellMainThread ShellExecutor executor) { + return new UnfoldTransitionHandler(progressProvider.get(), animator, + transactionPool, backgroundController, executor, transitions); } @Provides diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java index 73e6cba43ec0..1fc1215b6cea 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java @@ -76,6 +76,8 @@ public class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener { taskInfo.taskId); final Point positionInParent = taskInfo.positionInParent; mDataByTaskId.put(taskInfo.taskId, new TaskData(leash, positionInParent)); + mAnimatableTasksListener.onTaskAppeared(taskInfo); + if (Transitions.ENABLE_SHELL_TRANSITIONS) return; mSyncQueue.runInSync(t -> { // Reset several properties back to fullscreen (PiP, for example, leaves all these @@ -87,15 +89,15 @@ public class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener { t.show(leash); }); - mAnimatableTasksListener.onTaskAppeared(taskInfo); updateRecentsForVisibleFullscreenTask(taskInfo); } @Override public void onTaskInfoChanged(RunningTaskInfo taskInfo) { + mAnimatableTasksListener.onTaskInfoChanged(taskInfo); + if (Transitions.ENABLE_SHELL_TRANSITIONS) return; - mAnimatableTasksListener.onTaskInfoChanged(taskInfo); updateRecentsForVisibleFullscreenTask(taskInfo); final TaskData data = mDataByTaskId.get(taskInfo.taskId); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenUnfoldController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenUnfoldController.java index aa3868cfca84..99f15f65f74e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenUnfoldController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenUnfoldController.java @@ -17,213 +17,119 @@ package com.android.wm.shell.fullscreen; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; -import static android.util.MathUtils.lerp; -import static android.view.Display.DEFAULT_DISPLAY; -import android.animation.RectEvaluator; -import android.animation.TypeEvaluator; import android.annotation.NonNull; import android.app.ActivityManager; -import android.app.TaskInfo; -import android.content.Context; -import android.graphics.Matrix; -import android.graphics.Rect; -import android.util.SparseArray; -import android.view.InsetsSource; -import android.view.InsetsState; import android.view.SurfaceControl; -import com.android.internal.policy.ScreenDecorationsUtils; -import com.android.wm.shell.common.DisplayInsetsController; -import com.android.wm.shell.common.DisplayInsetsController.OnInsetsChangedListener; import com.android.wm.shell.unfold.ShellUnfoldProgressProvider; import com.android.wm.shell.unfold.ShellUnfoldProgressProvider.UnfoldListener; import com.android.wm.shell.unfold.UnfoldBackgroundController; +import com.android.wm.shell.unfold.UnfoldTransitionHandler; +import com.android.wm.shell.unfold.animation.FullscreenUnfoldTaskAnimator; import java.util.concurrent.Executor; /** * Controls full screen app unfold transition: animating cropping window and scaling when * folding or unfolding a foldable device. + * + * - When Shell transitions are disabled (legacy mode) this controller animates task surfaces + * when doing both fold and unfold. + * + * - When Shell transitions are enabled this controller animates the surfaces only when + * folding a foldable device. It's not done as a shell transition because we are not committed + * to the display size WM changes yet. + * In this case unfolding is handled by + * {@link com.android.wm.shell.unfold.UnfoldTransitionHandler}. */ -public final class FullscreenUnfoldController implements UnfoldListener, - OnInsetsChangedListener { - - private static final float[] FLOAT_9 = new float[9]; - private static final TypeEvaluator<Rect> RECT_EVALUATOR = new RectEvaluator(new Rect()); - - private static final float HORIZONTAL_START_MARGIN = 0.08f; - private static final float VERTICAL_START_MARGIN = 0.03f; - private static final float END_SCALE = 1f; - private static final float START_SCALE = END_SCALE - VERTICAL_START_MARGIN * 2; +public final class FullscreenUnfoldController implements UnfoldListener { private final Executor mExecutor; private final ShellUnfoldProgressProvider mProgressProvider; - private final DisplayInsetsController mDisplayInsetsController; - - private final SparseArray<AnimationContext> mAnimationContextByTaskId = new SparseArray<>(); private final UnfoldBackgroundController mBackgroundController; - - private InsetsSource mTaskbarInsetsSource; - - private final float mWindowCornerRadiusPx; - private final float mExpandedTaskBarHeight; - private final SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction(); + private final FullscreenUnfoldTaskAnimator mAnimator; + private final UnfoldTransitionHandler mUnfoldTransitionHandler; + + private boolean mShouldHandleAnimation = false; public FullscreenUnfoldController( - @NonNull Context context, @NonNull Executor executor, @NonNull UnfoldBackgroundController backgroundController, @NonNull ShellUnfoldProgressProvider progressProvider, - @NonNull DisplayInsetsController displayInsetsController + @NonNull UnfoldTransitionHandler unfoldTransitionHandler, + @NonNull FullscreenUnfoldTaskAnimator animator ) { mExecutor = executor; mProgressProvider = progressProvider; - mDisplayInsetsController = displayInsetsController; - mWindowCornerRadiusPx = ScreenDecorationsUtils.getWindowCornerRadius(context); - mExpandedTaskBarHeight = context.getResources().getDimensionPixelSize( - com.android.internal.R.dimen.taskbar_frame_height); mBackgroundController = backgroundController; + mUnfoldTransitionHandler = unfoldTransitionHandler; + mAnimator = animator; } /** * Initializes the controller */ public void init() { + mAnimator.init(); mProgressProvider.addListener(mExecutor, this); - mDisplayInsetsController.addInsetsChangedListener(DEFAULT_DISPLAY, this); + } + + @Override + public void onStateChangeStarted() { + mShouldHandleAnimation = !mUnfoldTransitionHandler.willHandleTransition(); } @Override public void onStateChangeProgress(float progress) { - if (mAnimationContextByTaskId.size() == 0) return; + if (!mAnimator.hasActiveTasks() || !mShouldHandleAnimation) return; mBackgroundController.ensureBackground(mTransaction); - - for (int i = mAnimationContextByTaskId.size() - 1; i >= 0; i--) { - final AnimationContext context = mAnimationContextByTaskId.valueAt(i); - - context.mCurrentCropRect.set(RECT_EVALUATOR - .evaluate(progress, context.mStartCropRect, context.mEndCropRect)); - - float scale = lerp(START_SCALE, END_SCALE, progress); - context.mMatrix.setScale(scale, scale, context.mCurrentCropRect.exactCenterX(), - context.mCurrentCropRect.exactCenterY()); - - mTransaction.setWindowCrop(context.mLeash, context.mCurrentCropRect) - .setMatrix(context.mLeash, context.mMatrix, FLOAT_9) - .setCornerRadius(context.mLeash, mWindowCornerRadiusPx); - } - + mAnimator.applyAnimationProgress(progress, mTransaction); mTransaction.apply(); } @Override public void onStateChangeFinished() { - for (int i = mAnimationContextByTaskId.size() - 1; i >= 0; i--) { - final AnimationContext context = mAnimationContextByTaskId.valueAt(i); - resetSurface(context); + if (!mShouldHandleAnimation) { + return; } + mShouldHandleAnimation = false; + mAnimator.resetAllSurfaces(mTransaction); mBackgroundController.removeBackground(mTransaction); mTransaction.apply(); } - @Override - public void insetsChanged(InsetsState insetsState) { - mTaskbarInsetsSource = insetsState.getSource(InsetsState.ITYPE_EXTRA_NAVIGATION_BAR); - for (int i = mAnimationContextByTaskId.size() - 1; i >= 0; i--) { - AnimationContext context = mAnimationContextByTaskId.valueAt(i); - context.update(mTaskbarInsetsSource, context.mTaskInfo); - } - } - /** * Called when a new matching task appeared */ public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) { - AnimationContext animationContext = new AnimationContext(leash, mTaskbarInsetsSource, - taskInfo); - mAnimationContextByTaskId.put(taskInfo.taskId, animationContext); + mAnimator.addTask(taskInfo, leash); } /** * Called when matching task changed */ public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) { - AnimationContext animationContext = mAnimationContextByTaskId.get(taskInfo.taskId); - if (animationContext != null) { - animationContext.update(mTaskbarInsetsSource, taskInfo); - } + mAnimator.onTaskInfoChanged(taskInfo); } /** * Called when matching task vanished */ public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) { - AnimationContext animationContext = mAnimationContextByTaskId.get(taskInfo.taskId); - if (animationContext != null) { - // PiP task has its own cleanup path, ignore surface reset to avoid conflict. - if (taskInfo.getWindowingMode() != WINDOWING_MODE_PINNED) { - resetSurface(animationContext); - } - mAnimationContextByTaskId.remove(taskInfo.taskId); + // PiP task has its own cleanup path, ignore surface reset to avoid conflict. + if (taskInfo.getWindowingMode() != WINDOWING_MODE_PINNED) { + mAnimator.resetSurface(taskInfo, mTransaction); } + mAnimator.removeTask(taskInfo); - if (mAnimationContextByTaskId.size() == 0) { + if (!mAnimator.hasActiveTasks()) { mBackgroundController.removeBackground(mTransaction); } mTransaction.apply(); } - - private void resetSurface(AnimationContext context) { - mTransaction - .setWindowCrop(context.mLeash, null) - .setCornerRadius(context.mLeash, 0.0F) - .setMatrix(context.mLeash, 1.0F, 0.0F, 0.0F, 1.0F) - .setPosition(context.mLeash, - (float) context.mTaskInfo.positionInParent.x, - (float) context.mTaskInfo.positionInParent.y); - } - - private class AnimationContext { - final SurfaceControl mLeash; - final Rect mStartCropRect = new Rect(); - final Rect mEndCropRect = new Rect(); - final Rect mCurrentCropRect = new Rect(); - final Matrix mMatrix = new Matrix(); - - TaskInfo mTaskInfo; - - private AnimationContext(SurfaceControl leash, - InsetsSource taskBarInsetsSource, - TaskInfo taskInfo) { - this.mLeash = leash; - update(taskBarInsetsSource, taskInfo); - } - - private void update(InsetsSource taskBarInsetsSource, TaskInfo taskInfo) { - mTaskInfo = taskInfo; - mStartCropRect.set(mTaskInfo.getConfiguration().windowConfiguration.getBounds()); - - if (taskBarInsetsSource != null) { - // Only insets the cropping window with task bar when it's expanded - if (taskBarInsetsSource.getFrame().height() >= mExpandedTaskBarHeight) { - mStartCropRect.inset(taskBarInsetsSource - .calculateVisibleInsets(mStartCropRect)); - } - } - - mEndCropRect.set(mStartCropRect); - - int horizontalMargin = (int) (mEndCropRect.width() * HORIZONTAL_START_MARGIN); - mStartCropRect.left = mEndCropRect.left + horizontalMargin; - mStartCropRect.right = mEndCropRect.right - horizontalMargin; - int verticalMargin = (int) (mEndCropRect.height() * VERTICAL_START_MARGIN); - mStartCropRect.top = mEndCropRect.top + verticalMargin; - mStartCropRect.bottom = mEndCropRect.bottom - verticalMargin; - } - } } 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 fbdf6f0b539f..d6b914138c38 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 @@ -294,6 +294,10 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, displayController.addDisplayWindowListener(this); } + public PipTransitionController getTransitionController() { + return mPipTransitionController; + } + public Rect getCurrentOrAnimatingBounds() { PipAnimationController.PipTransitionAnimator animator = mPipAnimationController.getCurrentAnimator(); 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 48df28ee4cde..5d17f85bb2ca 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 @@ -28,7 +28,6 @@ import static android.view.WindowManager.TRANSIT_OPEN; import static android.view.WindowManager.TRANSIT_PIP; import static android.view.WindowManager.transitTypeToString; import static android.window.TransitionInfo.FLAG_IS_DISPLAY; -import static android.window.TransitionInfo.FLAG_IS_WALLPAPER; import static com.android.wm.shell.pip.PipAnimationController.ANIM_TYPE_ALPHA; import static com.android.wm.shell.pip.PipAnimationController.ANIM_TYPE_BOUNDS; @@ -52,6 +51,7 @@ import android.graphics.Rect; import android.os.IBinder; import android.view.Surface; import android.view.SurfaceControl; +import android.view.WindowManager; import android.window.TransitionInfo; import android.window.TransitionRequestInfo; import android.window.WindowContainerToken; @@ -217,8 +217,9 @@ public class PipTransition extends PipTransitionController { } // Entering PIP. - if (isEnteringPip(info, mCurrentPipTaskToken)) { - return startEnterAnimation(info, startTransaction, finishTransaction, finishCallback); + if (isEnteringPip(info)) { + startEnterAnimation(info, startTransaction, finishTransaction, finishCallback); + return true; } // For transition that we don't animate, but contains the PIP leash, we need to update the @@ -245,16 +246,9 @@ public class PipTransition extends PipTransitionController { @Override public WindowContainerTransaction handleRequest(@NonNull IBinder transition, @NonNull TransitionRequestInfo request) { - if (request.getType() == TRANSIT_PIP) { + if (requestHasPipEnter(request)) { WindowContainerTransaction wct = new WindowContainerTransaction(); - if (mOneShotAnimationType == ANIM_TYPE_ALPHA) { - mRequestedEnterTransition = transition; - mRequestedEnterTask = request.getTriggerTask().token; - wct.setActivityWindowingMode(request.getTriggerTask().token, - WINDOWING_MODE_UNDEFINED); - final Rect destinationBounds = mPipBoundsAlgorithm.getEntryDestinationBounds(); - wct.setBounds(request.getTriggerTask().token, destinationBounds); - } + augmentRequest(transition, request, wct); return wct; } else { return null; @@ -262,6 +256,22 @@ public class PipTransition extends PipTransitionController { } @Override + public void augmentRequest(@NonNull IBinder transition, + @NonNull TransitionRequestInfo request, @NonNull WindowContainerTransaction outWCT) { + if (!requestHasPipEnter(request)) { + throw new IllegalStateException("Called PiP augmentRequest when request has no PiP"); + } + if (mOneShotAnimationType == ANIM_TYPE_ALPHA) { + mRequestedEnterTransition = transition; + mRequestedEnterTask = request.getTriggerTask().token; + outWCT.setActivityWindowingMode(request.getTriggerTask().token, + WINDOWING_MODE_UNDEFINED); + final Rect destinationBounds = mPipBoundsAlgorithm.getEntryDestinationBounds(); + outWCT.setBounds(request.getTriggerTask().token, destinationBounds); + } + } + + @Override public boolean handleRotateDisplay(int startRotation, int endRotation, WindowContainerTransaction wct) { if (mRequestedEnterTransition != null && mOneShotAnimationType == ANIM_TYPE_ALPHA) { @@ -559,92 +569,94 @@ public class PipTransition extends PipTransitionController { } /** Whether we should handle the given {@link TransitionInfo} animation as entering PIP. */ - private static boolean isEnteringPip(@NonNull TransitionInfo info, - @Nullable WindowContainerToken currentPipTaskToken) { + private boolean isEnteringPip(@NonNull TransitionInfo info) { for (int i = info.getChanges().size() - 1; i >= 0; --i) { final TransitionInfo.Change change = info.getChanges().get(i); - if (change.getTaskInfo() != null - && change.getTaskInfo().getWindowingMode() == WINDOWING_MODE_PINNED - && !change.getContainer().equals(currentPipTaskToken)) { - // We support TRANSIT_PIP type (from RootWindowContainer) or TRANSIT_OPEN (from apps - // that enter PiP instantly on opening, mostly from CTS/Flicker tests) - if (info.getType() == TRANSIT_PIP || info.getType() == TRANSIT_OPEN) { - return true; - } - // This can happen if the request to enter PIP happens when we are collecting for - // another transition, such as TRANSIT_CHANGE (display rotation). - if (info.getType() == TRANSIT_CHANGE) { - return true; - } + if (isEnteringPip(change, info.getType())) return true; + } + return false; + } - // Please file a bug to handle the unexpected transition type. - throw new IllegalStateException("Entering PIP with unexpected transition type=" - + transitTypeToString(info.getType())); + /** Whether a particular change is a window that is entering pip. */ + @Override + public boolean isEnteringPip(@NonNull TransitionInfo.Change change, + @WindowManager.TransitionType int transitType) { + if (change.getTaskInfo() != null + && change.getTaskInfo().getWindowingMode() == WINDOWING_MODE_PINNED + && !change.getContainer().equals(mCurrentPipTaskToken)) { + // We support TRANSIT_PIP type (from RootWindowContainer) or TRANSIT_OPEN (from apps + // that enter PiP instantly on opening, mostly from CTS/Flicker tests) + if (transitType == TRANSIT_PIP || transitType == TRANSIT_OPEN) { + return true; + } + // This can happen if the request to enter PIP happens when we are collecting for + // another transition, such as TRANSIT_CHANGE (display rotation). + if (transitType == TRANSIT_CHANGE) { + return true; } + + // Please file a bug to handle the unexpected transition type. + throw new IllegalStateException("Entering PIP with unexpected transition type=" + + transitTypeToString(transitType)); } return false; } - private boolean startEnterAnimation(@NonNull TransitionInfo info, + private void startEnterAnimation(@NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull Transitions.TransitionFinishCallback finishCallback) { - // Search for an Enter PiP transition (along with a show wallpaper one) + // Search for an Enter PiP transition TransitionInfo.Change enterPip = null; - TransitionInfo.Change wallpaper = null; for (int i = info.getChanges().size() - 1; i >= 0; --i) { final TransitionInfo.Change change = info.getChanges().get(i); if (change.getTaskInfo() != null && change.getTaskInfo().getWindowingMode() == WINDOWING_MODE_PINNED) { enterPip = change; - } else if ((change.getFlags() & FLAG_IS_WALLPAPER) != 0) { - wallpaper = change; } } if (enterPip == null) { - return false; + throw new IllegalStateException("Trying to start PiP animation without a pip" + + "participant"); } - // Keep track of the PIP task. - mCurrentPipTaskToken = enterPip.getContainer(); - mHasFadeOut = false; - if (mFinishCallback != null) { - callFinishCallback(null /* wct */); - mFinishTransaction = null; - throw new RuntimeException("Previous callback not called, aborting entering PIP."); - } - - // Show the wallpaper if there is a wallpaper change. - if (wallpaper != null) { - startTransaction.show(wallpaper.getLeash()); - startTransaction.setAlpha(wallpaper.getLeash(), 1.f); - } // Make sure other open changes are visible as entering PIP. Some may be hidden in // Transitions#setupStartState because the transition type is OPEN (such as auto-enter). for (int i = info.getChanges().size() - 1; i >= 0; --i) { final TransitionInfo.Change change = info.getChanges().get(i); - if (change == enterPip || change == wallpaper) { - continue; - } + if (change == enterPip) continue; if (isOpeningType(change.getMode())) { final SurfaceControl leash = change.getLeash(); startTransaction.show(leash).setAlpha(leash, 1.f); } } + startEnterAnimation(enterPip, startTransaction, finishTransaction, finishCallback); + } + + @Override + public void startEnterAnimation(@NonNull final TransitionInfo.Change pipChange, + @NonNull final SurfaceControl.Transaction startTransaction, + @NonNull final SurfaceControl.Transaction finishTransaction, + @NonNull final Transitions.TransitionFinishCallback finishCallback) { + if (mFinishCallback != null) { + callFinishCallback(null /* wct */); + mFinishTransaction = null; + throw new RuntimeException("Previous callback not called, aborting entering PIP."); + } + + // Keep track of the PIP task and animation. + mCurrentPipTaskToken = pipChange.getContainer(); + mHasFadeOut = false; mPipTransitionState.setTransitionState(PipTransitionState.ENTERING_PIP); mFinishCallback = finishCallback; mFinishTransaction = finishTransaction; - final int endRotation = mInFixedRotation ? mEndFixedRotation : enterPip.getEndRotation(); - return startEnterAnimation(enterPip.getTaskInfo(), enterPip.getLeash(), - startTransaction, finishTransaction, enterPip.getStartRotation(), - endRotation); - } - private boolean startEnterAnimation(final TaskInfo taskInfo, final SurfaceControl leash, - final SurfaceControl.Transaction startTransaction, - final SurfaceControl.Transaction finishTransaction, - final int startRotation, final int endRotation) { + final ActivityManager.RunningTaskInfo taskInfo = pipChange.getTaskInfo(); + final SurfaceControl leash = pipChange.getLeash(); + final int startRotation = pipChange.getStartRotation(); + final int endRotation = mInFixedRotation ? mEndFixedRotation : pipChange.getEndRotation(); + setBoundsStateForEntry(taskInfo.topActivity, taskInfo.pictureInPictureParams, taskInfo.topActivityInfo); final Rect destinationBounds = mPipBoundsAlgorithm.getEntryDestinationBounds(); @@ -657,7 +669,6 @@ public class PipTransition extends PipTransitionController { computeEnterPipRotatedBounds(rotationDelta, startRotation, endRotation, taskInfo, destinationBounds, sourceHintRect); } - PipAnimationController.PipTransitionAnimator animator; // Set corner radius for entering pip. mSurfaceTransactionHelper .crop(finishTransaction, leash, destinationBounds) @@ -694,7 +705,7 @@ public class PipTransition extends PipTransitionController { null /* callback */, false /* withStartDelay */); } mPipTransitionState.setInSwipePipToHomeTransition(false); - return true; + return; } if (rotationDelta != Surface.ROTATION_0) { @@ -702,6 +713,12 @@ public class PipTransition extends PipTransitionController { tmpTransform.postRotate(rotationDelta); startTransaction.setMatrix(leash, tmpTransform, new float[9]); } + if (mOneShotAnimationType == ANIM_TYPE_ALPHA) { + startTransaction.setAlpha(leash, 0f); + } + startTransaction.apply(); + + PipAnimationController.PipTransitionAnimator animator; if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) { animator = mPipAnimationController.getAnimator(taskInfo, leash, currentBounds, currentBounds, destinationBounds, sourceHintRect, TRANSITION_DIRECTION_TO_PIP, @@ -712,7 +729,6 @@ public class PipTransition extends PipTransitionController { animator.setUseContentOverlay(mContext); } } else if (mOneShotAnimationType == ANIM_TYPE_ALPHA) { - startTransaction.setAlpha(leash, 0f); animator = mPipAnimationController.getAnimator(taskInfo, leash, destinationBounds, 0f, 1f); mOneShotAnimationType = ANIM_TYPE_BOUNDS; @@ -720,7 +736,6 @@ public class PipTransition extends PipTransitionController { throw new RuntimeException("Unrecognized animation type: " + mOneShotAnimationType); } - startTransaction.apply(); animator.setTransitionDirection(TRANSITION_DIRECTION_TO_PIP) .setPipAnimationCallback(mPipAnimationCallback) .setDuration(mEnterExitAnimationDuration); @@ -731,8 +746,6 @@ public class PipTransition extends PipTransitionController { animator.setDestinationBounds(mPipBoundsAlgorithm.getEntryDestinationBounds()); } animator.start(); - - return true; } /** Computes destination bounds in old rotation and updates source hint rect if available. */ diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java index 24993c621e3c..28418be40c37 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java @@ -17,6 +17,7 @@ package com.android.wm.shell.pip; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; +import static android.view.WindowManager.TRANSIT_PIP; import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_REMOVE_STACK; import static com.android.wm.shell.pip.PipAnimationController.isInPipDirection; @@ -28,10 +29,16 @@ import android.content.ComponentName; import android.content.pm.ActivityInfo; import android.graphics.Rect; import android.os.Handler; +import android.os.IBinder; import android.os.Looper; import android.view.SurfaceControl; +import android.view.WindowManager; +import android.window.TransitionInfo; +import android.window.TransitionRequestInfo; import android.window.WindowContainerTransaction; +import androidx.annotation.NonNull; + import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.transition.Transitions; @@ -206,6 +213,30 @@ public abstract class PipTransitionController implements Transitions.TransitionH return false; } + /** @return whether the transition-request represents a pip-entry. */ + public boolean requestHasPipEnter(@NonNull TransitionRequestInfo request) { + return request.getType() == TRANSIT_PIP; + } + + /** Whether a particular change is a window that is entering pip. */ + public boolean isEnteringPip(@NonNull TransitionInfo.Change change, + @WindowManager.TransitionType int transitType) { + return false; + } + + /** Add PiP-related changes to `outWCT` for the given request. */ + public void augmentRequest(@NonNull IBinder transition, + @NonNull TransitionRequestInfo request, @NonNull WindowContainerTransaction outWCT) { + throw new IllegalStateException("Request isn't entering PiP"); + } + + /** Play a transition animation for entering PiP on a specific PiP change. */ + public void startEnterAnimation(@NonNull final TransitionInfo.Change pipChange, + @NonNull final SurfaceControl.Transaction startTransaction, + @NonNull final SurfaceControl.Transaction finishTransaction, + @NonNull final Transitions.TransitionFinishCallback finishCallback) { + } + /** * Callback interface for PiP transitions (both from and to PiP mode) */ diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java index ac7b9033b2b9..a2ff97247189 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java @@ -54,6 +54,7 @@ import com.android.wm.shell.pip.PipAnimationController; import com.android.wm.shell.pip.PipBoundsAlgorithm; import com.android.wm.shell.pip.PipBoundsState; import com.android.wm.shell.pip.PipTaskOrganizer; +import com.android.wm.shell.pip.PipTransitionController; import com.android.wm.shell.pip.PipUiEventLogger; import com.android.wm.shell.protolog.ShellProtoLogGroup; @@ -250,6 +251,10 @@ public class PipTouchHandler { }); } + public PipTransitionController getTransitionHandler() { + return mPipTaskOrganizer.getTransitionController(); + } + private void reloadResources() { final Resources res = mContext.getResources(); mBottomOffsetBufferPx = res.getDimensionPixelSize(R.dimen.pip_bottom_offset_buffer); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentTasks.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentTasks.aidl index 6e78fcba4a00..b71cc32a0347 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentTasks.aidl +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentTasks.aidl @@ -16,6 +16,8 @@ package com.android.wm.shell.recents; +import android.app.ActivityManager; + import com.android.wm.shell.recents.IRecentTasksListener; import com.android.wm.shell.util.GroupedRecentTaskInfo; @@ -38,4 +40,9 @@ interface IRecentTasks { * Gets the set of recent tasks. */ GroupedRecentTaskInfo[] getRecentTasks(int maxNum, int flags, int userId) = 3; + + /** + * Gets the set of running tasks. + */ + ActivityManager.RunningTaskInfo[] getRunningTasks(int maxNum) = 4; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentTasksListener.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentTasksListener.aidl index 8efa42830d80..59f72335678e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentTasksListener.aidl +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentTasksListener.aidl @@ -16,6 +16,8 @@ package com.android.wm.shell.recents; +import android.app.ActivityManager; + /** * Listener interface that Launcher attaches to SystemUI to get split-screen callbacks. */ @@ -25,4 +27,14 @@ oneway interface IRecentTasksListener { * Called when the set of recent tasks change. */ void onRecentTasksChanged(); + + /** + * Called when a running task appears. + */ + void onRunningTaskAppeared(in ActivityManager.RunningTaskInfo taskInfo); + + /** + * Called when a running task vanishes. + */ + void onRunningTaskVanished(in ActivityManager.RunningTaskInfo taskInfo); }
\ No newline at end of file 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 c166178e9bbd..d903d5b33780 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 @@ -17,6 +17,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.common.ExecutorUtils.executeRemoteCallWithTaskPermission; @@ -63,8 +64,9 @@ public class RecentTasksController implements TaskStackListenerCallback, private final ShellExecutor mMainExecutor; private final TaskStackListenerImpl mTaskStackListener; private final RecentTasks mImpl = new RecentTasksImpl(); + private IRecentTasksListener mListener; + private final boolean mIsDesktopMode; - private final ArrayList<Runnable> mCallbacks = new ArrayList<>(); // Mapping of split task ids, mappings are symmetrical (ie. if t1 is the taskid of a task in a // pair, then mSplitTasks[t1] = t2, and mSplitTasks[t2] = t1) private final SparseIntArray mSplitTasks = new SparseIntArray(); @@ -95,6 +97,7 @@ public class RecentTasksController implements TaskStackListenerCallback, RecentTasksController(Context context, TaskStackListenerImpl taskStackListener, ShellExecutor mainExecutor) { mContext = context; + mIsDesktopMode = mContext.getPackageManager().hasSystemFeature(FEATURE_PC); mTaskStackListener = taskStackListener; mMainExecutor = mainExecutor; } @@ -176,10 +179,15 @@ public class RecentTasksController implements TaskStackListenerCallback, notifyRecentTasksChanged(); } - public void onTaskRemoved(TaskInfo taskInfo) { + public void onTaskAdded(ActivityManager.RunningTaskInfo taskInfo) { + notifyRunningTaskAppeared(taskInfo); + } + + public void onTaskRemoved(ActivityManager.RunningTaskInfo taskInfo) { // Remove any split pairs associated with this task removeSplitPair(taskInfo.taskId); notifyRecentTasksChanged(); + notifyRunningTaskVanished(taskInfo); } public void onTaskWindowingModeChanged(TaskInfo taskInfo) { @@ -189,19 +197,50 @@ public class RecentTasksController implements TaskStackListenerCallback, @VisibleForTesting void notifyRecentTasksChanged() { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENT_TASKS, "Notify recent tasks changed"); - for (int i = 0; i < mCallbacks.size(); i++) { - mCallbacks.get(i).run(); + if (mListener == null) { + return; + } + try { + mListener.onRecentTasksChanged(); + } catch (RemoteException e) { + Slog.w(TAG, "Failed call notifyRecentTasksChanged", e); } } - private void registerRecentTasksListener(Runnable listener) { - if (!mCallbacks.contains(listener)) { - mCallbacks.add(listener); + /** + * Notify the running task listener that a task appeared on desktop environment. + */ + private void notifyRunningTaskAppeared(ActivityManager.RunningTaskInfo taskInfo) { + if (mListener == null || !mIsDesktopMode || taskInfo.realActivity == null) { + return; + } + try { + mListener.onRunningTaskAppeared(taskInfo); + } catch (RemoteException e) { + Slog.w(TAG, "Failed call onRunningTaskAppeared", e); + } + } + + /** + * Notify the running task listener that a task was removed on desktop environment. + */ + private void notifyRunningTaskVanished(ActivityManager.RunningTaskInfo taskInfo) { + if (mListener == null || !mIsDesktopMode || taskInfo.realActivity == null) { + return; + } + try { + mListener.onRunningTaskVanished(taskInfo); + } catch (RemoteException e) { + Slog.w(TAG, "Failed call onRunningTaskVanished", e); } } - private void unregisterRecentTasksListener(Runnable listener) { - mCallbacks.remove(listener); + private void registerRecentTasksListener(IRecentTasksListener listener) { + mListener = listener; + } + + private void unregisterRecentTasksListener() { + mListener = null; } @VisibleForTesting @@ -280,19 +319,28 @@ public class RecentTasksController implements TaskStackListenerCallback, private RecentTasksController mController; private final SingleInstanceRemoteListener<RecentTasksController, IRecentTasksListener> mListener; - private final Runnable mRecentTasksListener = - new Runnable() { - @Override - public void run() { - mListener.call(l -> l.onRecentTasksChanged()); - } - }; + private final IRecentTasksListener mRecentTasksListener = new IRecentTasksListener.Stub() { + @Override + public void onRecentTasksChanged() throws RemoteException { + mListener.call(l -> l.onRecentTasksChanged()); + } + + @Override + public void onRunningTaskAppeared(ActivityManager.RunningTaskInfo taskInfo) { + mListener.call(l -> l.onRunningTaskAppeared(taskInfo)); + } + + @Override + public void onRunningTaskVanished(ActivityManager.RunningTaskInfo taskInfo) { + mListener.call(l -> l.onRunningTaskVanished(taskInfo)); + } + }; public IRecentTasksImpl(RecentTasksController controller) { mController = controller; mListener = new SingleInstanceRemoteListener<>(controller, c -> c.registerRecentTasksListener(mRecentTasksListener), - c -> c.unregisterRecentTasksListener(mRecentTasksListener)); + c -> c.unregisterRecentTasksListener()); } /** @@ -331,5 +379,16 @@ public class RecentTasksController implements TaskStackListenerCallback, true /* blocking */); return out[0]; } + + @Override + public ActivityManager.RunningTaskInfo[] getRunningTasks(int maxNum) { + final ActivityManager.RunningTaskInfo[][] tasks = + new ActivityManager.RunningTaskInfo[][] {null}; + executeRemoteCallWithTaskPermission(mController, "getRunningTasks", + (controller) -> tasks[0] = ActivityTaskManager.getInstance().getTasks(maxNum) + .toArray(new ActivityManager.RunningTaskInfo[0]), + true /* blocking */); + return tasks[0]; + } } }
\ No newline at end of file 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 dd2634ca36d9..55fe4f066091 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 @@ -108,7 +108,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, static final int EXIT_REASON_ROOT_TASK_VANISHED = 6; static final int EXIT_REASON_SCREEN_LOCKED = 7; static final int EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP = 8; - static final int EXIT_REASON_CHILD_TASK_ENTER_PIP = 9; + public static final int EXIT_REASON_CHILD_TASK_ENTER_PIP = 9; @IntDef(value = { EXIT_REASON_UNKNOWN, EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW, @@ -198,6 +198,10 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, return mStageCoordinator.isSplitScreenVisible(); } + public StageCoordinator getTransitionHandler() { + return mStageCoordinator; + } + @Nullable public ActivityManager.RunningTaskInfo getTaskInfo(@SplitPosition int splitPosition) { if (!isSplitScreenVisible() || splitPosition == SPLIT_POSITION_UNDEFINED) { 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 cd121ed41fdd..f8221d5aae24 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,7 +21,6 @@ import static android.view.WindowManager.TRANSIT_CLOSE; import static android.view.WindowManager.TRANSIT_OPEN; import static android.view.WindowManager.TRANSIT_TO_BACK; import static android.view.WindowManager.TRANSIT_TO_FRONT; -import static android.window.TransitionInfo.FLAG_FIRST_CUSTOM; import static com.android.wm.shell.splitscreen.SplitScreen.stageTypeToString; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DRAG_DIVIDER; @@ -58,9 +57,6 @@ import java.util.ArrayList; class SplitScreenTransitions { private static final String TAG = "SplitScreenTransitions"; - /** Flag applied to a transition change to identify it as a divider bar for animation. */ - public static final int FLAG_IS_DIVIDER_BAR = FLAG_FIRST_CUSTOM; - private final TransactionPool mTransactionPool; private final Transitions mTransitions; private final Runnable mOnFinish; @@ -70,7 +66,7 @@ class SplitScreenTransitions { IBinder mPendingRecent = null; private IBinder mAnimatingTransition = null; - private OneShotRemoteHandler mPendingRemoteHandler = null; + OneShotRemoteHandler mPendingRemoteHandler = null; private OneShotRemoteHandler mActiveRemoteHandler = null; private final Transitions.TransitionFinishCallback mRemoteFinishCB = this::onFinish; @@ -94,7 +90,8 @@ class SplitScreenTransitions { @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull Transitions.TransitionFinishCallback finishCallback, - @NonNull WindowContainerToken mainRoot, @NonNull WindowContainerToken sideRoot) { + @NonNull WindowContainerToken mainRoot, @NonNull WindowContainerToken sideRoot, + @NonNull WindowContainerToken topRoot) { mFinishCallback = finishCallback; mAnimatingTransition = transition; if (mPendingRemoteHandler != null) { @@ -104,12 +101,12 @@ class SplitScreenTransitions { mPendingRemoteHandler = null; return; } - playInternalAnimation(transition, info, startTransaction, mainRoot, sideRoot); + playInternalAnimation(transition, info, startTransaction, mainRoot, sideRoot, topRoot); } private void playInternalAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t, @NonNull WindowContainerToken mainRoot, - @NonNull WindowContainerToken sideRoot) { + @NonNull WindowContainerToken sideRoot, @NonNull WindowContainerToken topRoot) { mFinishTransaction = mTransactionPool.acquire(); // Play some place-holder fade animations @@ -140,7 +137,10 @@ class SplitScreenTransitions { endBounds.offset(-info.getRootOffset().x, -info.getRootOffset().y); startExampleResizeAnimation(leash, startBounds, endBounds); } - if (change.getParent() != null) { + boolean isRootOrSplitSideRoot = change.getParent() == null + || topRoot.equals(change.getParent()); + // For enter or exit, we only want to animate the side roots but not the top-root. + if (!isRootOrSplitSideRoot || topRoot.equals(change.getContainer())) { continue; } @@ -187,27 +187,28 @@ class SplitScreenTransitions { } /** Starts a transition to dismiss split. */ - IBinder startDismissTransition(@Nullable IBinder transition, WindowContainerTransaction wct, + IBinder startDismissTransition(WindowContainerTransaction wct, Transitions.TransitionHandler handler, @SplitScreen.StageType int dismissTop, @SplitScreenController.ExitReason int reason) { final int type = reason == EXIT_REASON_DRAG_DIVIDER ? TRANSIT_SPLIT_DISMISS_SNAP : TRANSIT_SPLIT_DISMISS; - if (transition == null) { - transition = mTransitions.startTransition(type, wct, handler); - } + IBinder transition = mTransitions.startTransition(type, wct, handler); + setDismissTransition(transition, dismissTop, reason); + return transition; + } + + /** Sets a transition to dismiss split. */ + void setDismissTransition(@NonNull IBinder transition, @SplitScreen.StageType int dismissTop, + @SplitScreenController.ExitReason int reason) { mPendingDismiss = new DismissTransition(transition, reason, dismissTop); ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " splitTransition " + " deduced Dismiss due to %s. toTop=%s", exitReasonToString(reason), stageTypeToString(dismissTop)); - return transition; } - IBinder startRecentTransition(@Nullable IBinder transition, WindowContainerTransaction wct, - Transitions.TransitionHandler handler, @Nullable RemoteTransition remoteTransition) { - if (transition == null) { - transition = mTransitions.startTransition(TRANSIT_OPEN, wct, handler); - } + void setRecentTransition(@NonNull IBinder transition, + @Nullable RemoteTransition remoteTransition) { mPendingRecent = transition; if (remoteTransition != null) { @@ -219,7 +220,6 @@ class SplitScreenTransitions { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " splitTransition " + " deduced Enter recent panel"); - return transition; } void mergeAnimation(IBinder transition, TransitionInfo info, SurfaceControl.Transaction t, 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 9d6e34ddd9d7..06f7eda00d1f 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 @@ -28,6 +28,7 @@ import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_TO_BACK; import static android.view.WindowManager.TRANSIT_TO_FRONT; import static android.view.WindowManager.transitTypeToString; +import static android.window.TransitionInfo.FLAG_FIRST_CUSTOM; import static android.window.TransitionInfo.FLAG_IS_DISPLAY; import static com.android.wm.shell.common.split.SplitLayout.PARALLAX_ALIGN_CENTER; @@ -47,7 +48,6 @@ import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_UNKNOWN; import static com.android.wm.shell.splitscreen.SplitScreenController.exitReasonToString; -import static com.android.wm.shell.splitscreen.SplitScreenTransitions.FLAG_IS_DIVIDER_BAR; import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS; import static com.android.wm.shell.transition.Transitions.TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE; import static com.android.wm.shell.transition.Transitions.TRANSIT_SPLIT_SCREEN_PAIR_OPEN; @@ -127,12 +127,15 @@ import javax.inject.Provider; * This rules are mostly implemented in {@link #onStageVisibilityChanged(StageListenerImpl)} and * {@link #onStageHasChildrenChanged(StageListenerImpl).} */ -class StageCoordinator implements SplitLayout.SplitLayoutHandler, +public class StageCoordinator implements SplitLayout.SplitLayoutHandler, DisplayController.OnDisplaysChangedListener, Transitions.TransitionHandler, ShellTaskOrganizer.TaskListener { private static final String TAG = StageCoordinator.class.getSimpleName(); + /** Flag applied to a transition change to identify it as a divider bar for animation. */ + public static final int FLAG_IS_DIVIDER_BAR = FLAG_FIRST_CUSTOM; + private final SurfaceSession mSurfaceSession = new SurfaceSession(); private final MainStage mMainStage; @@ -636,7 +639,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, if (ENABLE_SHELL_TRANSITIONS) { final WindowContainerTransaction wct = new WindowContainerTransaction(); prepareExitSplitScreen(mTopStageAfterFoldDismiss, wct); - mSplitTransitions.startDismissTransition(null /* transition */, wct, this, + mSplitTransitions.startDismissTransition(wct, this, mTopStageAfterFoldDismiss, EXIT_REASON_DEVICE_FOLDED); } else { exitSplitScreen( @@ -666,8 +669,8 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, final int dismissTop = mainStageVisible ? STAGE_TYPE_MAIN : STAGE_TYPE_SIDE; final WindowContainerTransaction wct = new WindowContainerTransaction(); prepareExitSplitScreen(dismissTop, wct); - mSplitTransitions.startDismissTransition(null /* transition */, wct, this, - dismissTop, EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP); + mSplitTransitions.startDismissTransition(wct, this, dismissTop, + EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP); } } } @@ -729,10 +732,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, .setWindowCrop(mSideStage.mRootLeash, null); }); - // Hide divider and reset its position. - mSplitLayout.resetDividerPosition(); - mSplitLayout.release(); - mTopStageAfterFoldDismiss = STAGE_TYPE_UNDEFINED; + onTransitionAnimationComplete(); Slog.i(TAG, "applyExitSplitScreen, reason = " + exitReasonToString(exitReason)); // Log the exit if (childrenToTop != null) { @@ -1128,8 +1128,10 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, final int dismissTop = mainStageToTop ? STAGE_TYPE_MAIN : STAGE_TYPE_SIDE; final WindowContainerTransaction wct = new WindowContainerTransaction(); prepareExitSplitScreen(dismissTop, wct); - mSplitTransitions.startDismissTransition( - null /* transition */, wct, this, dismissTop, EXIT_REASON_DRAG_DIVIDER); + if (mRootTaskInfo != null) { + wct.setDoNotPip(mRootTaskInfo.token); + } + mSplitTransitions.startDismissTransition(wct, this, dismissTop, EXIT_REASON_DRAG_DIVIDER); } @Override @@ -1318,7 +1320,8 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, @Nullable TransitionRequestInfo request) { final ActivityManager.RunningTaskInfo triggerTask = request.getTriggerTask(); if (triggerTask == null) { - if (mMainStage.isActive()) { + if (isSplitActive()) { + // Check if the display is rotating. final TransitionRequestInfo.DisplayChange displayChange = request.getDisplayChange(); if (request.getType() == TRANSIT_CHANGE && displayChange != null @@ -1345,7 +1348,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, mRecentTasks.ifPresent(recentTasks -> recentTasks.removeSplitPair(triggerTask.taskId)); } - if (mMainStage.isActive()) { + if (isSplitActive()) { // Try to handle everything while in split-screen, so return a WCT even if it's empty. ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " split is active so using split" + "Transition to handle request. triggerTask=%d type=%s mainChildren=%d" @@ -1360,7 +1363,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, int dismissTop = getStageType(stage) == STAGE_TYPE_MAIN ? STAGE_TYPE_SIDE : STAGE_TYPE_MAIN; prepareExitSplitScreen(dismissTop, out); - mSplitTransitions.startDismissTransition(transition, out, this, dismissTop, + mSplitTransitions.setDismissTransition(transition, dismissTop, EXIT_REASON_APP_FINISHED); } } else if (isOpening && inFullscreen) { @@ -1370,12 +1373,12 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, } else if (activityType == ACTIVITY_TYPE_HOME || activityType == ACTIVITY_TYPE_RECENTS) { // Enter overview panel, so start recent transition. - mSplitTransitions.startRecentTransition(transition, out, this, + mSplitTransitions.setRecentTransition(transition, request.getRemoteTransition()); } else { // Occluded by the other fullscreen task, so dismiss both. prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, out); - mSplitTransitions.startDismissTransition(transition, out, this, + mSplitTransitions.setDismissTransition(transition, STAGE_TYPE_UNDEFINED, EXIT_REASON_UNKNOWN); } } @@ -1390,6 +1393,33 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, return out; } + /** + * This is used for mixed scenarios. For such scenarios, just make sure to include exiting + * split or entering split when appropriate. + */ + public void addEnterOrExitIfNeeded(@Nullable TransitionRequestInfo request, + @NonNull WindowContainerTransaction outWCT) { + final ActivityManager.RunningTaskInfo triggerTask = request.getTriggerTask(); + if (triggerTask != null && triggerTask.displayId != mDisplayId) { + // Skip handling task on the other display. + return; + } + final @WindowManager.TransitionType int type = request.getType(); + if (isSplitActive() && !isOpeningType(type) + && (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0)) { + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " One of the splits became " + + "empty during a mixed transition (one not handled by split)," + + " so make sure split-screen state is cleaned-up. " + + "mainStageCount=%d sideStageCount=%d", mMainStage.getChildCount(), + mSideStage.getChildCount()); + prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, outWCT); + } + } + + public boolean isSplitActive() { + return mMainStage.isActive(); + } + @Override public void mergeAnimation(IBinder transition, TransitionInfo info, SurfaceControl.Transaction t, IBinder mergeTarget, @@ -1405,6 +1435,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, final SurfaceControl.Transaction t = mTransactionPool.acquire(); finishEnterSplitScreen(t); mSplitTransitions.mPendingEnter = null; + mSplitTransitions.mPendingRemoteHandler = null; t.apply(); mTransactionPool.release(t); } @@ -1478,11 +1509,13 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, if (!shouldAnimate) return false; mSplitTransitions.playAnimation(transition, info, startTransaction, finishTransaction, - finishCallback, mMainStage.mRootTaskInfo.token, mSideStage.mRootTaskInfo.token); + finishCallback, mMainStage.mRootTaskInfo.token, mSideStage.mRootTaskInfo.token, + mRootTaskInfo.token); return true; } - void onTransitionAnimationComplete() { + /** Called to clean-up state and do house-keeping after the animation is done. */ + public void onTransitionAnimationComplete() { // If still playing, let it finish. if (!mMainStage.isActive()) { // Update divider state after animation so that it is still around and positioned @@ -1546,8 +1579,8 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, return true; } - private boolean startPendingDismissAnimation( - @NonNull SplitScreenTransitions.DismissTransition dismissTransition, + /** Synchronize split-screen state with transition and make appropriate preparations. */ + public void prepareDismissAnimation(@StageType int toStage, @ExitReason int dismissReason, @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t, @NonNull SurfaceControl.Transaction finishT) { // Make some noise if things aren't totally expected. These states shouldn't effect @@ -1580,7 +1613,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, mRecentTasks.ifPresent(recentTasks -> { // Notify recents if we are exiting in a way that breaks the pair, and disable further // updates to splits in the recents until we enter split again - if (shouldBreakPairedTaskInRecents(dismissTransition.mReason) && mShouldUpdateRecents) { + if (shouldBreakPairedTaskInRecents(dismissReason) && mShouldUpdateRecents) { for (TransitionInfo.Change change : info.getChanges()) { final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo(); if (taskInfo != null @@ -1597,30 +1630,38 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, // Wait until after animation to update divider // Reset crops so they don't interfere with subsequent launches - t.setWindowCrop(mMainStage.mRootLeash, null); - t.setWindowCrop(mSideStage.mRootLeash, null); + t.setCrop(mMainStage.mRootLeash, null); + t.setCrop(mSideStage.mRootLeash, null); - if (dismissTransition.mDismissTop == STAGE_TYPE_UNDEFINED) { - logExit(dismissTransition.mReason); - // TODO: Have a proper remote for this. Until then, though, reset state and use the - // normal animation stuff (which falls back to the normal launcher remote). - mSplitLayout.release(t); - mSplitTransitions.mPendingDismiss = null; - return false; + if (toStage == STAGE_TYPE_UNDEFINED) { + logExit(dismissReason); } else { - logExitToStage(dismissTransition.mReason, - dismissTransition.mDismissTop == STAGE_TYPE_MAIN); + logExitToStage(dismissReason, toStage == STAGE_TYPE_MAIN); } addDividerBarToTransition(info, t, false /* show */); - // We're dismissing split by moving the other one to fullscreen. - // Since we don't have any animations for this yet, just use the internal example - // animations. // Hide divider and dim layer on transition finished. setDividerVisibility(false, finishT); finishT.hide(mMainStage.mDimLayer); finishT.hide(mSideStage.mDimLayer); + } + + private boolean startPendingDismissAnimation( + @NonNull SplitScreenTransitions.DismissTransition dismissTransition, + @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t, + @NonNull SurfaceControl.Transaction finishT) { + prepareDismissAnimation(dismissTransition.mDismissTop, dismissTransition.mReason, info, + t, finishT); + if (dismissTransition.mDismissTop == STAGE_TYPE_UNDEFINED) { + // TODO: Have a proper remote for this. Until then, though, reset state and use the + // normal animation stuff (which falls back to the normal launcher remote). + t.hide(mSplitLayout.getDividerLeash()); + mSplitLayout.release(t); + mSplitTransitions.mPendingDismiss = null; + return false; + } + return true; } @@ -1786,15 +1827,17 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, @Override public void onNoLongerSupportMultiWindow() { if (mMainStage.isActive()) { + final boolean isMainStage = mMainStageListener == this; if (!ENABLE_SHELL_TRANSITIONS) { - StageCoordinator.this.exitSplitScreen(null /* childrenToTop */, + StageCoordinator.this.exitSplitScreen(isMainStage ? mMainStage : mSideStage, EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW); + return; } + final int stageType = isMainStage ? STAGE_TYPE_MAIN : STAGE_TYPE_SIDE; final WindowContainerTransaction wct = new WindowContainerTransaction(); - prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, wct); - mSplitTransitions.startDismissTransition(null /* transition */, wct, - StageCoordinator.this, STAGE_TYPE_UNDEFINED, + prepareExitSplitScreen(stageType, wct); + mSplitTransitions.startDismissTransition(wct,StageCoordinator.this, stageType, EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW); } } 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 9fd5d2003873..4b12eb86b568 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 @@ -268,13 +268,13 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener { mChildrenTaskInfo.remove(taskId); mChildrenLeashes.remove(taskId); mCallbacks.onChildTaskStatusChanged(taskId, false /* present */, taskInfo.isVisible); - if (taskInfo.getWindowingMode() == WINDOWING_MODE_PINNED) { - mCallbacks.onChildTaskEnterPip(taskId); - } if (ENABLE_SHELL_TRANSITIONS) { // Status is managed/synchronized by the transition lifecycle. return; } + if (taskInfo.getWindowingMode() == WINDOWING_MODE_PINNED) { + mCallbacks.onChildTaskEnterPip(taskId); + } sendStatusChanged(); } else { throw new IllegalArgumentException(this + "\n Unknown task: " + taskInfo diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java new file mode 100644 index 000000000000..1ffe26df729f --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java @@ -0,0 +1,253 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.transition; + +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.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED; +import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_CHILD_TASK_ENTER_PIP; +import static com.android.wm.shell.splitscreen.StageCoordinator.FLAG_IS_DIVIDER_BAR; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.os.IBinder; +import android.view.SurfaceControl; +import android.view.WindowManager; +import android.window.TransitionInfo; +import android.window.TransitionRequestInfo; +import android.window.WindowContainerTransaction; + +import com.android.internal.protolog.common.ProtoLog; +import com.android.wm.shell.pip.PipTransitionController; +import com.android.wm.shell.protolog.ShellProtoLogGroup; +import com.android.wm.shell.splitscreen.StageCoordinator; + +import java.util.ArrayList; + +/** + * A handler for dealing with transitions involving multiple other handlers. For example: an + * activity in split-screen going into PiP. + */ +public class DefaultMixedHandler implements Transitions.TransitionHandler { + + private final Transitions mPlayer; + private final PipTransitionController mPipHandler; + private final StageCoordinator mSplitHandler; + + private static class MixedTransition { + static final int TYPE_ENTER_PIP_FROM_SPLIT = 1; + + final int mType; + final IBinder mTransition; + + Transitions.TransitionFinishCallback mFinishCallback = null; + + /** + * Mixed transitions are made up of multiple "parts". This keeps track of how many + * parts are currently animating. + */ + int mInFlightSubAnimations = 0; + + MixedTransition(int type, IBinder transition) { + mType = type; + mTransition = transition; + } + } + private final ArrayList<MixedTransition> mActiveTransitions = new ArrayList<>(); + + public DefaultMixedHandler(@NonNull Transitions player, + @NonNull PipTransitionController pipHandler, @NonNull StageCoordinator splitHandler) { + mPlayer = player; + mPipHandler = pipHandler; + mSplitHandler = splitHandler; + } + + @Nullable + @Override + public WindowContainerTransaction handleRequest(@NonNull IBinder transition, + @NonNull TransitionRequestInfo request) { + if (mPipHandler.requestHasPipEnter(request) && mSplitHandler.isSplitActive()) { + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Got a PiP-enter request while " + + "Split-Screen is active, so treat it as Mixed."); + if (request.getRemoteTransition() != null) { + throw new IllegalStateException("Unexpected remote transition in" + + "pip-enter-from-split request"); + } + mActiveTransitions.add(new MixedTransition(MixedTransition.TYPE_ENTER_PIP_FROM_SPLIT, + transition)); + + WindowContainerTransaction out = new WindowContainerTransaction(); + mPipHandler.augmentRequest(transition, request, out); + mSplitHandler.addEnterOrExitIfNeeded(request, out); + return out; + } + return null; + } + + private TransitionInfo subCopy(@NonNull TransitionInfo info, + @WindowManager.TransitionType int newType) { + final TransitionInfo out = new TransitionInfo(newType, info.getFlags()); + for (int i = 0; i < info.getChanges().size(); ++i) { + out.getChanges().add(info.getChanges().get(i)); + } + out.setRootLeash(info.getRootLeash(), info.getRootOffset().x, info.getRootOffset().y); + out.setAnimationOptions(info.getAnimationOptions()); + return out; + } + + private boolean isHomeOpening(@NonNull TransitionInfo.Change change) { + return change.getTaskInfo() != null + && change.getTaskInfo().getActivityType() != ACTIVITY_TYPE_HOME; + } + + private boolean isWallpaper(@NonNull TransitionInfo.Change change) { + return (change.getFlags() & FLAG_IS_WALLPAPER) != 0; + } + + @Override + public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, + @NonNull SurfaceControl.Transaction startTransaction, + @NonNull SurfaceControl.Transaction finishTransaction, + @NonNull Transitions.TransitionFinishCallback finishCallback) { + MixedTransition mixed = null; + for (int i = mActiveTransitions.size() - 1; i >= 0; --i) { + if (mActiveTransitions.get(i).mTransition != transition) continue; + mixed = mActiveTransitions.remove(i); + break; + } + if (mixed == null) return false; + + if (mixed.mType == MixedTransition.TYPE_ENTER_PIP_FROM_SPLIT) { + return animateEnterPipFromSplit(mixed, info, startTransaction, finishTransaction, + finishCallback); + } else { + throw new IllegalStateException("Starting mixed animation without a known mixed type? " + + mixed.mType); + } + } + + private boolean animateEnterPipFromSplit(@NonNull final MixedTransition mixed, + @NonNull TransitionInfo info, + @NonNull SurfaceControl.Transaction startTransaction, + @NonNull SurfaceControl.Transaction finishTransaction, + @NonNull Transitions.TransitionFinishCallback finishCallback) { + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Animating a mixed transition for " + + "entering PIP while Split-Screen is active."); + TransitionInfo.Change pipChange = null; + TransitionInfo.Change wallpaper = null; + final TransitionInfo everythingElse = subCopy(info, TRANSIT_TO_BACK); + boolean homeIsOpening = false; + for (int i = info.getChanges().size() - 1; i >= 0; --i) { + TransitionInfo.Change change = info.getChanges().get(i); + if (mPipHandler.isEnteringPip(change, info.getType())) { + if (pipChange != null) { + throw new IllegalStateException("More than 1 pip-entering changes in one" + + " transition? " + info); + } + pipChange = change; + // going backwards, so remove-by-index is fine. + everythingElse.getChanges().remove(i); + } else if (isHomeOpening(change)) { + homeIsOpening = true; + } else if (isWallpaper(change)) { + wallpaper = change; + } + } + if (pipChange == null) { + // um, something probably went wrong. + return false; + } + final boolean isGoingHome = homeIsOpening; + mixed.mFinishCallback = finishCallback; + Transitions.TransitionFinishCallback finishCB = (wct, wctCB) -> { + --mixed.mInFlightSubAnimations; + if (mixed.mInFlightSubAnimations > 0) return; + if (isGoingHome) { + mSplitHandler.onTransitionAnimationComplete(); + } + mixed.mFinishCallback.onTransitionFinished(wct, wctCB); + }; + if (isGoingHome) { + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Animation is actually mixed " + + "since entering-PiP caused us to leave split and return home."); + // We need to split the transition into 2 parts: the pip part (animated by pip) + // and the dismiss-part (animated by launcher). + mixed.mInFlightSubAnimations = 2; + // immediately make the wallpaper visible (so that we don't see it pop-in during + // the time it takes to start recents animation (which is remote). + if (wallpaper != null) { + startTransaction.show(wallpaper.getLeash()).setAlpha(wallpaper.getLeash(), 1.f); + } + // make a new startTransaction because pip's startEnterAnimation "consumes" it so + // we need a separate one to send over to launcher. + SurfaceControl.Transaction otherStartT = new SurfaceControl.Transaction(); + // Let split update internal state for dismiss. + mSplitHandler.prepareDismissAnimation(STAGE_TYPE_UNDEFINED, + EXIT_REASON_CHILD_TASK_ENTER_PIP, everythingElse, otherStartT, + finishTransaction); + + // We are trying to accommodate launcher's close animation which can't handle the + // divider-bar, so if split-handler is closing the divider-bar, just hide it and remove + // from transition info. + for (int i = everythingElse.getChanges().size() - 1; i >= 0; --i) { + if ((everythingElse.getChanges().get(i).getFlags() & FLAG_IS_DIVIDER_BAR) != 0) { + everythingElse.getChanges().remove(i); + break; + } + } + + mPipHandler.startEnterAnimation(pipChange, startTransaction, finishTransaction, + finishCB); + // Dispatch the rest of the transition normally. This will most-likely be taken by + // recents or default handler. + mPlayer.dispatchTransition(mixed.mTransition, everythingElse, otherStartT, + finishTransaction, finishCB, this); + } else { + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Not leaving split, so just " + + "forward animation to Pip-Handler."); + // This happens if the pip-ing activity is in a multi-activity task (and thus a + // new pip task is spawned). In this case, we don't actually exit split so we can + // just let pip transition handle the animation verbatim. + mixed.mInFlightSubAnimations = 1; + mPipHandler.startAnimation(mixed.mTransition, info, startTransaction, finishTransaction, + finishCB); + } + return true; + } + + @Override + public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, + @NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget, + @NonNull Transitions.TransitionFinishCallback finishCallback) { + } + + @Override + public void onTransitionMerged(@NonNull IBinder transition) { + MixedTransition mixed = null; + for (int i = mActiveTransitions.size() - 1; i >= 0; --i) { + if (mActiveTransitions.get(i).mTransition != transition) continue; + mixed = mActiveTransitions.remove(i); + break; + } + if (mixed == null) return; + if (mixed.mType == MixedTransition.TYPE_ENTER_PIP_FROM_SPLIT) { + mPipHandler.onTransitionMerged(transition); + } + } +} 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 435d67087f34..e4c94264be2c 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 @@ -435,33 +435,42 @@ public class Transitions implements RemoteCallable<Transitions> { playing.mToken, (wct, cb) -> onFinish(merging.mToken, wct, cb)); } - boolean startAnimation(@NonNull ActiveTransition active, TransitionHandler handler) { - return handler.startAnimation(active.mToken, active.mInfo, active.mStartT, active.mFinishT, - (wct, cb) -> onFinish(active.mToken, wct, cb)); - } - - void playTransition(@NonNull ActiveTransition active) { + private void playTransition(@NonNull ActiveTransition active) { setupAnimHierarchy(active.mInfo, active.mStartT, active.mFinishT); // If a handler already chose to run this animation, try delegating to it first. if (active.mHandler != null) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " try firstHandler %s", active.mHandler); - if (startAnimation(active, active.mHandler)) { + boolean consumed = active.mHandler.startAnimation(active.mToken, active.mInfo, + active.mStartT, active.mFinishT, (wct, cb) -> onFinish(active.mToken, wct, cb)); + if (consumed) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " animated by firstHandler"); return; } } - // Otherwise give every other handler a chance (in order) + // Otherwise give every other handler a chance + active.mHandler = dispatchTransition(active.mToken, active.mInfo, active.mStartT, + active.mFinishT, (wct, cb) -> onFinish(active.mToken, wct, cb), active.mHandler); + } + + /** + * Gives every handler (in order) a chance to animate until one consumes the transition. + * @return the handler which consumed the transition. + */ + TransitionHandler dispatchTransition(@NonNull IBinder transition, @NonNull TransitionInfo info, + @NonNull SurfaceControl.Transaction startT, @NonNull SurfaceControl.Transaction finishT, + @NonNull TransitionFinishCallback finishCB, @Nullable TransitionHandler skip) { for (int i = mHandlers.size() - 1; i >= 0; --i) { - if (mHandlers.get(i) == active.mHandler) continue; + if (mHandlers.get(i) == skip) continue; ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " try handler %s", mHandlers.get(i)); - if (startAnimation(active, mHandlers.get(i))) { + boolean consumed = mHandlers.get(i).startAnimation(transition, info, startT, finishT, + finishCB); + if (consumed) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " animated by %s", mHandlers.get(i)); - active.mHandler = mHandlers.get(i); - return; + return mHandlers.get(i); } } throw new IllegalStateException( diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldBackgroundController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldBackgroundController.java index 9faf454261d3..86ca292399cb 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldBackgroundController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldBackgroundController.java @@ -79,7 +79,7 @@ public class UnfoldBackgroundController { } private float[] getBackgroundColor(Context context) { - int colorInt = context.getResources().getColor(R.color.unfold_transition_background); + int colorInt = context.getResources().getColor(R.color.taskbar_background); return new float[]{ (float) red(colorInt) / 255.0F, (float) green(colorInt) / 255.0F, 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 639603941c18..af78f2d7d870 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,15 +34,20 @@ import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.transition.Transitions.TransitionFinishCallback; import com.android.wm.shell.transition.Transitions.TransitionHandler; import com.android.wm.shell.unfold.ShellUnfoldProgressProvider.UnfoldListener; +import com.android.wm.shell.unfold.animation.FullscreenUnfoldTaskAnimator; -import java.util.ArrayList; -import java.util.List; import java.util.concurrent.Executor; +/** + * Transition handler that is responsible for animating app surfaces when unfolding of foldable + * devices. It does not handle the folding animation, which is done in + * {@link com.android.wm.shell.fullscreen.FullscreenUnfoldController}. + */ public class UnfoldTransitionHandler implements TransitionHandler, UnfoldListener { private final ShellUnfoldProgressProvider mUnfoldProgressProvider; private final Transitions mTransitions; + private final UnfoldBackgroundController mUnfoldBackgroundController; private final Executor mExecutor; private final TransactionPool mTransactionPool; @@ -51,17 +56,22 @@ public class UnfoldTransitionHandler implements TransitionHandler, UnfoldListene @Nullable private IBinder mTransition; - private final List<TransitionInfo.Change> mAnimatedFullscreenTasks = new ArrayList<>(); + private final FullscreenUnfoldTaskAnimator mFullscreenAnimator; public UnfoldTransitionHandler(ShellUnfoldProgressProvider unfoldProgressProvider, - TransactionPool transactionPool, Executor executor, Transitions transitions) { + FullscreenUnfoldTaskAnimator animator, TransactionPool transactionPool, + UnfoldBackgroundController unfoldBackgroundController, + Executor executor, Transitions transitions) { mUnfoldProgressProvider = unfoldProgressProvider; + mFullscreenAnimator = animator; mTransactionPool = transactionPool; + mUnfoldBackgroundController = unfoldBackgroundController; mExecutor = executor; mTransitions = transitions; } public void init() { + mFullscreenAnimator.init(); mTransitions.addHandler(this); mUnfoldProgressProvider.addListener(mExecutor, this); } @@ -71,40 +81,36 @@ public class UnfoldTransitionHandler implements TransitionHandler, UnfoldListene @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull TransitionFinishCallback finishCallback) { - if (transition != mTransition) return false; + mUnfoldBackgroundController.ensureBackground(startTransaction); startTransaction.apply(); - mAnimatedFullscreenTasks.clear(); + mFullscreenAnimator.clearTasks(); info.getChanges().forEach(change -> { final boolean allowedToAnimate = change.getTaskInfo() != null + && change.getTaskInfo().isVisible() && change.getTaskInfo().getWindowingMode() == WINDOWING_MODE_FULLSCREEN && change.getTaskInfo().getActivityType() != ACTIVITY_TYPE_HOME && change.getMode() == TRANSIT_CHANGE; if (allowedToAnimate) { - mAnimatedFullscreenTasks.add(change); + mFullscreenAnimator.addTask(change.getTaskInfo(), change.getLeash()); } }); + mFullscreenAnimator.resetAllSurfaces(finishTransaction); + mUnfoldBackgroundController.removeBackground(finishTransaction); mFinishCallback = finishCallback; - mTransition = null; return true; } @Override public void onStateChangeProgress(float progress) { - mAnimatedFullscreenTasks.forEach(change -> { - final SurfaceControl.Transaction transaction = mTransactionPool.acquire(); - - // TODO: this is a placeholder animation, replace with a spec version in the next CLs - final float testScale = 0.8f + 0.2f * progress; - transaction.setScale(change.getLeash(), testScale, testScale); - - transaction.apply(); - mTransactionPool.release(transaction); - }); + final SurfaceControl.Transaction transaction = mTransactionPool.acquire(); + mFullscreenAnimator.applyAnimationProgress(progress, transaction); + transaction.apply(); + mTransactionPool.release(transaction); } @Override @@ -112,7 +118,8 @@ public class UnfoldTransitionHandler implements TransitionHandler, UnfoldListene if (mFinishCallback != null) { mFinishCallback.onTransitionFinished(null, null); mFinishCallback = null; - mAnimatedFullscreenTasks.clear(); + mTransition = null; + mFullscreenAnimator.clearTasks(); } } @@ -120,11 +127,14 @@ public class UnfoldTransitionHandler implements TransitionHandler, UnfoldListene @Override public WindowContainerTransaction handleRequest(@NonNull IBinder transition, @NonNull TransitionRequestInfo request) { - if (request.getType() == TRANSIT_CHANGE && request.getDisplayChange() != null - && request.getDisplayChange().isPhysicalDisplayChanged()) { + if (request.getType() == TRANSIT_CHANGE && request.getDisplayChange() != null) { mTransition = transition; return new WindowContainerTransaction(); } return null; } + + public boolean willHandleTransition() { + return mTransition != null; + } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/FullscreenUnfoldTaskAnimator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/FullscreenUnfoldTaskAnimator.java new file mode 100644 index 000000000000..6ec5512c22ec --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/FullscreenUnfoldTaskAnimator.java @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.unfold.animation; + +import static android.util.MathUtils.lerp; +import static android.view.Display.DEFAULT_DISPLAY; + +import android.animation.RectEvaluator; +import android.animation.TypeEvaluator; +import android.app.TaskInfo; +import android.content.Context; +import android.graphics.Matrix; +import android.graphics.Rect; +import android.util.SparseArray; +import android.view.InsetsSource; +import android.view.InsetsState; +import android.view.SurfaceControl; +import android.view.SurfaceControl.Transaction; + +import com.android.internal.policy.ScreenDecorationsUtils; +import com.android.wm.shell.common.DisplayInsetsController; + +/** + * This helper class contains logic that calculates scaling and cropping parameters + * for the folding/unfolding animation. As an input it receives TaskInfo objects and + * surfaces leashes and as an output it could fill surface transactions with required + * transformations. + * + * This class is used by + * {@link com.android.wm.shell.unfold.UnfoldTransitionHandler} and + * {@link com.android.wm.shell.fullscreen.FullscreenUnfoldController}. They use independent + * instances of FullscreenUnfoldTaskAnimator. + */ +public class FullscreenUnfoldTaskAnimator implements + DisplayInsetsController.OnInsetsChangedListener { + + private static final float[] FLOAT_9 = new float[9]; + private static final TypeEvaluator<Rect> RECT_EVALUATOR = new RectEvaluator(new Rect()); + + private static final float HORIZONTAL_START_MARGIN = 0.08f; + private static final float VERTICAL_START_MARGIN = 0.03f; + private static final float END_SCALE = 1f; + private static final float START_SCALE = END_SCALE - VERTICAL_START_MARGIN * 2; + + private final SparseArray<AnimationContext> mAnimationContextByTaskId = new SparseArray<>(); + private final int mExpandedTaskBarHeight; + private final float mWindowCornerRadiusPx; + private final DisplayInsetsController mDisplayInsetsController; + + private InsetsSource mTaskbarInsetsSource; + + public FullscreenUnfoldTaskAnimator(Context context, + DisplayInsetsController displayInsetsController) { + mDisplayInsetsController = displayInsetsController; + mExpandedTaskBarHeight = context.getResources().getDimensionPixelSize( + com.android.internal.R.dimen.taskbar_frame_height); + mWindowCornerRadiusPx = ScreenDecorationsUtils.getWindowCornerRadius(context); + } + + public void init() { + mDisplayInsetsController.addInsetsChangedListener(DEFAULT_DISPLAY, this); + } + + @Override + public void insetsChanged(InsetsState insetsState) { + mTaskbarInsetsSource = insetsState.getSource(InsetsState.ITYPE_EXTRA_NAVIGATION_BAR); + for (int i = mAnimationContextByTaskId.size() - 1; i >= 0; i--) { + AnimationContext context = mAnimationContextByTaskId.valueAt(i); + context.update(mTaskbarInsetsSource, context.mTaskInfo); + } + } + + public boolean hasActiveTasks() { + return mAnimationContextByTaskId.size() > 0; + } + + public void addTask(TaskInfo taskInfo, SurfaceControl leash) { + AnimationContext animationContext = new AnimationContext(leash, mTaskbarInsetsSource, + taskInfo); + mAnimationContextByTaskId.put(taskInfo.taskId, animationContext); + } + + public void onTaskInfoChanged(TaskInfo taskInfo) { + AnimationContext animationContext = mAnimationContextByTaskId.get(taskInfo.taskId); + if (animationContext != null) { + animationContext.update(mTaskbarInsetsSource, taskInfo); + } + } + + public void removeTask(TaskInfo taskInfo) { + mAnimationContextByTaskId.remove(taskInfo.taskId); + } + + public void clearTasks() { + mAnimationContextByTaskId.clear(); + } + + public void resetSurface(TaskInfo taskInfo, Transaction transaction) { + final AnimationContext context = mAnimationContextByTaskId.get(taskInfo.taskId); + if (context != null) { + resetSurface(context, transaction); + } + } + + public void applyAnimationProgress(float progress, Transaction transaction) { + if (mAnimationContextByTaskId.size() == 0) return; + + for (int i = mAnimationContextByTaskId.size() - 1; i >= 0; i--) { + final AnimationContext context = mAnimationContextByTaskId.valueAt(i); + + context.mCurrentCropRect.set(RECT_EVALUATOR + .evaluate(progress, context.mStartCropRect, context.mEndCropRect)); + + float scale = lerp(START_SCALE, END_SCALE, progress); + context.mMatrix.setScale(scale, scale, context.mCurrentCropRect.exactCenterX(), + context.mCurrentCropRect.exactCenterY()); + + transaction.setWindowCrop(context.mLeash, context.mCurrentCropRect) + .setMatrix(context.mLeash, context.mMatrix, FLOAT_9) + .setCornerRadius(context.mLeash, mWindowCornerRadiusPx) + .show(context.mLeash) + ; + } + } + + public void resetAllSurfaces(Transaction transaction) { + for (int i = mAnimationContextByTaskId.size() - 1; i >= 0; i--) { + final AnimationContext context = mAnimationContextByTaskId.valueAt(i); + resetSurface(context, transaction); + } + } + + private void resetSurface(AnimationContext context, Transaction transaction) { + transaction + .setWindowCrop(context.mLeash, null) + .setCornerRadius(context.mLeash, 0.0F) + .setMatrix(context.mLeash, 1.0F, 0.0F, 0.0F, 1.0F) + .setPosition(context.mLeash, + (float) context.mTaskInfo.positionInParent.x, + (float) context.mTaskInfo.positionInParent.y); + } + + private class AnimationContext { + final SurfaceControl mLeash; + final Rect mStartCropRect = new Rect(); + final Rect mEndCropRect = new Rect(); + final Rect mCurrentCropRect = new Rect(); + final Matrix mMatrix = new Matrix(); + + TaskInfo mTaskInfo; + + private AnimationContext(SurfaceControl leash, InsetsSource taskBarInsetsSource, + TaskInfo taskInfo) { + mLeash = leash; + update(taskBarInsetsSource, taskInfo); + } + + private void update(InsetsSource taskBarInsetsSource, TaskInfo taskInfo) { + mTaskInfo = taskInfo; + mStartCropRect.set(mTaskInfo.getConfiguration().windowConfiguration.getBounds()); + + if (taskBarInsetsSource != null) { + // Only insets the cropping window with task bar when it's expanded + if (taskBarInsetsSource.getFrame().height() >= mExpandedTaskBarHeight) { + mStartCropRect.inset(taskBarInsetsSource + .calculateVisibleInsets(mStartCropRect)); + } + } + + mEndCropRect.set(mStartCropRect); + + int horizontalMargin = (int) (mEndCropRect.width() * HORIZONTAL_START_MARGIN); + mStartCropRect.left = mEndCropRect.left + horizontalMargin; + mStartCropRect.right = mEndCropRect.right - horizontalMargin; + int verticalMargin = (int) (mEndCropRect.height() * VERTICAL_START_MARGIN); + mStartCropRect.top = mEndCropRect.top + verticalMargin; + mStartCropRect.bottom = mEndCropRect.bottom - verticalMargin; + } + } +} 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 50f6bd7b4927..9ef8c322d105 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 @@ -30,11 +30,13 @@ 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; import static java.lang.Integer.MAX_VALUE; import android.app.ActivityManager; import android.content.Context; +import android.content.pm.PackageManager; import android.graphics.Rect; import android.view.SurfaceControl; @@ -77,6 +79,7 @@ public class RecentTasksControllerTest extends ShellTestCase { @Before public void setUp() { mMainExecutor = new TestShellExecutor(); + when(mContext.getPackageManager()).thenReturn(mock(PackageManager.class)); mRecentTasksController = spy(new RecentTasksController(mContext, mTaskStackListener, mMainExecutor)); mShellTaskOrganizer = new ShellTaskOrganizer(mMainExecutor, mContext, 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 a55f737f2f25..0e39527a9e5f 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 @@ -334,7 +334,7 @@ public class SplitTransitionTests extends ShellTestCase { TransitionInfo info = new TransitionInfo(TRANSIT_TO_BACK, 0); info.addChange(mainChange); info.addChange(sideChange); - IBinder transition = mSplitScreenTransitions.startDismissTransition(null, + IBinder transition = mSplitScreenTransitions.startDismissTransition( new WindowContainerTransaction(), mStageCoordinator, EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW, STAGE_TYPE_SIDE); boolean accepted = mStageCoordinator.startAnimation(transition, info, @@ -356,7 +356,7 @@ public class SplitTransitionTests extends ShellTestCase { TransitionInfo info = new TransitionInfo(TRANSIT_TO_BACK, 0); info.addChange(mainChange); info.addChange(sideChange); - IBinder transition = mSplitScreenTransitions.startDismissTransition(null, + IBinder transition = mSplitScreenTransitions.startDismissTransition( new WindowContainerTransaction(), mStageCoordinator, EXIT_REASON_DRAG_DIVIDER, STAGE_TYPE_SIDE); mMainStage.onTaskVanished(mMainChild); diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp index c80fb188e70f..8a379d581532 100644 --- a/libs/androidfw/Android.bp +++ b/libs/androidfw/Android.bp @@ -33,6 +33,7 @@ license { cc_defaults { name: "libandroidfw_defaults", + cpp_std: "gnu++2b", cflags: [ "-Werror", "-Wunreachable-code", diff --git a/libs/androidfw/include/androidfw/StringPiece.h b/libs/androidfw/include/androidfw/StringPiece.h index 921877dc4982..fac2fa4fa575 100644 --- a/libs/androidfw/include/androidfw/StringPiece.h +++ b/libs/androidfw/include/androidfw/StringPiece.h @@ -288,12 +288,12 @@ inline ::std::basic_string<TChar>& operator+=(::std::basic_string<TChar>& lhs, template <typename TChar> inline bool operator==(const ::std::basic_string<TChar>& lhs, const BasicStringPiece<TChar>& rhs) { - return rhs == lhs; + return BasicStringPiece<TChar>(lhs) == rhs; } template <typename TChar> inline bool operator!=(const ::std::basic_string<TChar>& lhs, const BasicStringPiece<TChar>& rhs) { - return rhs != lhs; + return BasicStringPiece<TChar>(lhs) != rhs; } } // namespace android diff --git a/libs/hwui/DeviceInfo.h b/libs/hwui/DeviceInfo.h index d5fee3f667a9..2e6e36a9ff22 100644 --- a/libs/hwui/DeviceInfo.h +++ b/libs/hwui/DeviceInfo.h @@ -16,7 +16,9 @@ #ifndef DEVICEINFO_H #define DEVICEINFO_H +#include <SkColorSpace.h> #include <SkImageInfo.h> +#include <SkRefCnt.h> #include <android/data_space.h> #include <mutex> diff --git a/libs/hwui/HardwareBitmapUploader.cpp b/libs/hwui/HardwareBitmapUploader.cpp index c24cabb287de..7291cab364e2 100644 --- a/libs/hwui/HardwareBitmapUploader.cpp +++ b/libs/hwui/HardwareBitmapUploader.cpp @@ -22,8 +22,11 @@ #include <GLES2/gl2ext.h> #include <GLES3/gl3.h> #include <GrDirectContext.h> +#include <SkBitmap.h> #include <SkCanvas.h> #include <SkImage.h> +#include <SkImageInfo.h> +#include <SkRefCnt.h> #include <gui/TraceUtils.h> #include <utils/GLUtils.h> #include <utils/NdkUtils.h> diff --git a/libs/hwui/HardwareBitmapUploader.h b/libs/hwui/HardwareBitmapUploader.h index 81057a24c29c..00ee99648889 100644 --- a/libs/hwui/HardwareBitmapUploader.h +++ b/libs/hwui/HardwareBitmapUploader.h @@ -17,6 +17,9 @@ #pragma once #include <hwui/Bitmap.h> +#include <SkRefCnt.h> + +class SkBitmap; namespace android::uirenderer { diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp index 4cce87ad1a2f..79953aa6adc9 100644 --- a/libs/hwui/Readback.cpp +++ b/libs/hwui/Readback.cpp @@ -26,6 +26,18 @@ #include "pipeline/skia/LayerDrawable.h" #include "renderthread/EglManager.h" #include "renderthread/VulkanManager.h" +#include <SkBitmap.h> +#include <SkBlendMode.h> +#include <SkCanvas.h> +#include <SkColorSpace.h> +#include <SkImage.h> +#include <SkImageInfo.h> +#include <SkMatrix.h> +#include <SkPaint.h> +#include <SkRect.h> +#include <SkRefCnt.h> +#include <SkSamplingOptions.h> +#include <SkSurface.h> #include "utils/Color.h" #include "utils/MathUtils.h" #include "utils/NdkUtils.h" diff --git a/libs/hwui/Readback.h b/libs/hwui/Readback.h index d0d748ff5c16..aa6e43c3bc27 100644 --- a/libs/hwui/Readback.h +++ b/libs/hwui/Readback.h @@ -20,7 +20,11 @@ #include "Rect.h" #include "renderthread/RenderThread.h" -#include <SkBitmap.h> +#include <SkRefCnt.h> + +class SkBitmap; +class SkImage; +struct SkRect; namespace android { class Bitmap; diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp index a285462eef74..f5ebfd5d9e23 100644 --- a/libs/hwui/RecordingCanvas.cpp +++ b/libs/hwui/RecordingCanvas.cpp @@ -29,10 +29,14 @@ #include "SkDrawShadowInfo.h" #include "SkImage.h" #include "SkImageFilter.h" +#include "SkImageInfo.h" #include "SkLatticeIter.h" #include "SkMath.h" +#include "SkPaint.h" #include "SkPicture.h" +#include "SkRRect.h" #include "SkRSXform.h" +#include "SkRect.h" #include "SkRegion.h" #include "SkTextBlob.h" #include "SkVertices.h" diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h index 212b4e72dcb2..35bec9335d7c 100644 --- a/libs/hwui/RecordingCanvas.h +++ b/libs/hwui/RecordingCanvas.h @@ -34,6 +34,8 @@ #include <SkRuntimeEffect.h> #include <vector> +class SkRRect; + namespace android { namespace uirenderer { diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp index 53c6db0cdf3a..023d6bf0b673 100644 --- a/libs/hwui/SkiaCanvas.cpp +++ b/libs/hwui/SkiaCanvas.cpp @@ -27,6 +27,7 @@ #include <SkAndroidFrameworkUtils.h> #include <SkAnimatedImage.h> +#include <SkBitmap.h> #include <SkCanvasPriv.h> #include <SkCanvasStateUtils.h> #include <SkColorFilter.h> @@ -36,8 +37,13 @@ #include <SkGraphics.h> #include <SkImage.h> #include <SkImagePriv.h> +#include <SkMatrix.h> +#include <SkPaint.h> #include <SkPicture.h> #include <SkRSXform.h> +#include <SkRRect.h> +#include <SkRect.h> +#include <SkRefCnt.h> #include <SkShader.h> #include <SkTemplates.h> #include <SkTextBlob.h> diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h index 715007cdcd3b..c6313f6c3a88 100644 --- a/libs/hwui/SkiaCanvas.h +++ b/libs/hwui/SkiaCanvas.h @@ -33,6 +33,8 @@ #include <cassert> #include <optional> +class SkRRect; + namespace android { // Holds an SkCanvas reference plus additional native data. diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp index 983c7766273a..536ff781badc 100644 --- a/libs/hwui/VectorDrawable.cpp +++ b/libs/hwui/VectorDrawable.cpp @@ -21,9 +21,10 @@ #include <utils/Log.h> #include "PathParser.h" -#include "SkColorFilter.h" +#include "SkImage.h" #include "SkImageInfo.h" -#include "SkShader.h" +#include "SkSamplingOptions.h" +#include "SkScalar.h" #include "hwui/Paint.h" #ifdef __ANDROID__ diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h index 30bb04ae8361..c92654c479c1 100644 --- a/libs/hwui/VectorDrawable.h +++ b/libs/hwui/VectorDrawable.h @@ -31,6 +31,7 @@ #include <SkPath.h> #include <SkPathMeasure.h> #include <SkRect.h> +#include <SkRefCnt.h> #include <SkShader.h> #include <SkSurface.h> diff --git a/libs/hwui/apex/android_bitmap.cpp b/libs/hwui/apex/android_bitmap.cpp index bc6bc456ba5a..c442a7b1d17c 100644 --- a/libs/hwui/apex/android_bitmap.cpp +++ b/libs/hwui/apex/android_bitmap.cpp @@ -24,6 +24,11 @@ #include <GraphicsJNI.h> #include <hwui/Bitmap.h> +#include <SkBitmap.h> +#include <SkColorSpace.h> +#include <SkImageInfo.h> +#include <SkRefCnt.h> +#include <SkStream.h> #include <utils/Color.h> using namespace android; diff --git a/libs/hwui/apex/android_canvas.cpp b/libs/hwui/apex/android_canvas.cpp index 2a939efed9bb..905b123076a2 100644 --- a/libs/hwui/apex/android_canvas.cpp +++ b/libs/hwui/apex/android_canvas.cpp @@ -23,7 +23,9 @@ #include <utils/Color.h> #include <SkBitmap.h> +#include <SkColorSpace.h> #include <SkSurface.h> +#include <SkRefCnt.h> using namespace android; diff --git a/libs/hwui/canvas/CanvasOps.h b/libs/hwui/canvas/CanvasOps.h index fdc97a4fd8ba..2dcbca8273e7 100644 --- a/libs/hwui/canvas/CanvasOps.h +++ b/libs/hwui/canvas/CanvasOps.h @@ -17,13 +17,19 @@ #pragma once #include <SkAndroidFrameworkUtils.h> +#include <SkBlendMode.h> #include <SkCanvas.h> -#include <SkPath.h> -#include <SkRegion.h> -#include <SkVertices.h> +#include <SkClipOp.h> #include <SkImage.h> +#include <SkPaint.h> +#include <SkPath.h> #include <SkPicture.h> +#include <SkRRect.h> +#include <SkRect.h> +#include <SkRegion.h> #include <SkRuntimeEffect.h> +#include <SkSamplingOptions.h> +#include <SkVertices.h> #include <log/log.h> diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp index 67f47580a70f..feafc2372442 100644 --- a/libs/hwui/hwui/Bitmap.cpp +++ b/libs/hwui/hwui/Bitmap.cpp @@ -35,9 +35,15 @@ #endif #include <SkCanvas.h> +#include <SkColor.h> +#include <SkEncodedImageFormat.h> +#include <SkHighContrastFilter.h> +#include <SkImageEncoder.h> #include <SkImagePriv.h> +#include <SkPixmap.h> +#include <SkRect.h> +#include <SkStream.h> #include <SkWebpEncoder.h> -#include <SkHighContrastFilter.h> #include <limits> namespace android { diff --git a/libs/hwui/hwui/Bitmap.h b/libs/hwui/hwui/Bitmap.h index 94a047c06ced..133f1fe0a1e7 100644 --- a/libs/hwui/hwui/Bitmap.h +++ b/libs/hwui/hwui/Bitmap.h @@ -19,9 +19,9 @@ #include <SkColorFilter.h> #include <SkColorSpace.h> #include <SkImage.h> -#include <SkImage.h> #include <SkImageInfo.h> #include <SkPixelRef.h> +#include <SkRefCnt.h> #include <cutils/compiler.h> #ifdef __ANDROID__ // Layoutlib does not support hardware acceleration #include <android/hardware_buffer.h> diff --git a/libs/hwui/hwui/BlurDrawLooper.cpp b/libs/hwui/hwui/BlurDrawLooper.cpp index 270d24af99fd..d4b0198d015d 100644 --- a/libs/hwui/hwui/BlurDrawLooper.cpp +++ b/libs/hwui/hwui/BlurDrawLooper.cpp @@ -15,6 +15,7 @@ */ #include "BlurDrawLooper.h" +#include <SkColorSpace.h> #include <SkMaskFilter.h> namespace android { diff --git a/libs/hwui/hwui/Canvas.cpp b/libs/hwui/hwui/Canvas.cpp index b046f45d9c57..cd8af3d933b1 100644 --- a/libs/hwui/hwui/Canvas.cpp +++ b/libs/hwui/hwui/Canvas.cpp @@ -26,6 +26,7 @@ #include "hwui/PaintFilter.h" #include <SkFontMetrics.h> +#include <SkRRect.h> namespace android { diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h index 82777646f3a2..7378351ef771 100644 --- a/libs/hwui/hwui/Canvas.h +++ b/libs/hwui/hwui/Canvas.h @@ -31,6 +31,7 @@ class SkAnimatedImage; class SkCanvasState; +class SkRRect; class SkRuntimeShaderBuilder; class SkVertices; diff --git a/libs/hwui/hwui/ImageDecoder.h b/libs/hwui/hwui/ImageDecoder.h index cef2233fc371..b6d73b39d8d0 100644 --- a/libs/hwui/hwui/ImageDecoder.h +++ b/libs/hwui/hwui/ImageDecoder.h @@ -17,9 +17,11 @@ #include <SkAndroidCodec.h> #include <SkCodec.h> +#include <SkColorSpace.h> #include <SkImageInfo.h> #include <SkPngChunkReader.h> #include <SkRect.h> +#include <SkRefCnt.h> #include <SkSize.h> #include <cutils/compiler.h> diff --git a/libs/hwui/hwui/MinikinSkia.cpp b/libs/hwui/hwui/MinikinSkia.cpp index 2db3ace1cd43..34cb4aef70d9 100644 --- a/libs/hwui/hwui/MinikinSkia.cpp +++ b/libs/hwui/hwui/MinikinSkia.cpp @@ -16,10 +16,13 @@ #include "MinikinSkia.h" -#include <SkFontDescriptor.h> #include <SkFont.h> +#include <SkFontDescriptor.h> #include <SkFontMetrics.h> #include <SkFontMgr.h> +#include <SkRect.h> +#include <SkScalar.h> +#include <SkStream.h> #include <SkTypeface.h> #include <log/log.h> diff --git a/libs/hwui/jni/AnimatedImageDrawable.cpp b/libs/hwui/jni/AnimatedImageDrawable.cpp index c40b858268be..373e893b9a25 100644 --- a/libs/hwui/jni/AnimatedImageDrawable.cpp +++ b/libs/hwui/jni/AnimatedImageDrawable.cpp @@ -21,8 +21,11 @@ #include <SkAndroidCodec.h> #include <SkAnimatedImage.h> #include <SkColorFilter.h> +#include <SkEncodedImageFormat.h> #include <SkPicture.h> #include <SkPictureRecorder.h> +#include <SkRect.h> +#include <SkRefCnt.h> #include <hwui/AnimatedImageDrawable.h> #include <hwui/ImageDecoder.h> #include <hwui/Canvas.h> diff --git a/libs/hwui/jni/Bitmap.cpp b/libs/hwui/jni/Bitmap.cpp index 5db0783cf83e..94cea65897cf 100755 --- a/libs/hwui/jni/Bitmap.cpp +++ b/libs/hwui/jni/Bitmap.cpp @@ -2,17 +2,25 @@ #define LOG_TAG "Bitmap" #include "Bitmap.h" +#include "GraphicsJNI.h" #include "SkBitmap.h" +#include "SkBlendMode.h" #include "SkCanvas.h" #include "SkColor.h" #include "SkColorSpace.h" -#include "SkPixelRef.h" +#include "SkData.h" #include "SkImageEncoder.h" #include "SkImageInfo.h" -#include "GraphicsJNI.h" +#include "SkPaint.h" +#include "SkPixelRef.h" +#include "SkPixmap.h" +#include "SkPoint.h" +#include "SkRefCnt.h" #include "SkStream.h" +#include "SkTypes.h" #include "SkWebpEncoder.h" + #include "android_nio_utils.h" #include "CreateJavaOutputStreamAdaptor.h" #include <hwui/Paint.h> diff --git a/libs/hwui/jni/Bitmap.h b/libs/hwui/jni/Bitmap.h index 73eca3aa8ef8..21a93f066d9b 100644 --- a/libs/hwui/jni/Bitmap.h +++ b/libs/hwui/jni/Bitmap.h @@ -19,7 +19,6 @@ #include <jni.h> #include <android/bitmap.h> -class SkBitmap; struct SkImageInfo; namespace android { diff --git a/libs/hwui/jni/BitmapFactory.cpp b/libs/hwui/jni/BitmapFactory.cpp index 4e9daa4b0c16..320d3322904f 100644 --- a/libs/hwui/jni/BitmapFactory.cpp +++ b/libs/hwui/jni/BitmapFactory.cpp @@ -8,9 +8,19 @@ #include "MimeType.h" #include "NinePatchPeeker.h" #include "SkAndroidCodec.h" +#include "SkBitmap.h" +#include "SkBlendMode.h" #include "SkCanvas.h" +#include "SkColorSpace.h" +#include "SkEncodedImageFormat.h" +#include "SkImageInfo.h" #include "SkMath.h" +#include "SkPaint.h" #include "SkPixelRef.h" +#include "SkRect.h" +#include "SkRefCnt.h" +#include "SkSamplingOptions.h" +#include "SkSize.h" #include "SkStream.h" #include "SkString.h" #include "SkUtils.h" diff --git a/libs/hwui/jni/BitmapRegionDecoder.cpp b/libs/hwui/jni/BitmapRegionDecoder.cpp index 1c20415dcc8f..eb56ae310231 100644 --- a/libs/hwui/jni/BitmapRegionDecoder.cpp +++ b/libs/hwui/jni/BitmapRegionDecoder.cpp @@ -25,6 +25,7 @@ #include "BitmapRegionDecoder.h" #include "SkBitmap.h" #include "SkCodec.h" +#include "SkColorSpace.h" #include "SkData.h" #include "SkStream.h" diff --git a/libs/hwui/jni/ByteBufferStreamAdaptor.cpp b/libs/hwui/jni/ByteBufferStreamAdaptor.cpp index b10540cb3fbd..97dbc9ac171f 100644 --- a/libs/hwui/jni/ByteBufferStreamAdaptor.cpp +++ b/libs/hwui/jni/ByteBufferStreamAdaptor.cpp @@ -2,6 +2,7 @@ #include "GraphicsJNI.h" #include "Utils.h" +#include <SkData.h> #include <SkStream.h> using namespace android; diff --git a/libs/hwui/jni/FontFamily.cpp b/libs/hwui/jni/FontFamily.cpp index ce5ac382aeff..acc1b0424030 100644 --- a/libs/hwui/jni/FontFamily.cpp +++ b/libs/hwui/jni/FontFamily.cpp @@ -24,6 +24,7 @@ #include "SkData.h" #include "SkFontMgr.h" #include "SkRefCnt.h" +#include "SkStream.h" #include "SkTypeface.h" #include "Utils.h" #include "fonts/Font.h" diff --git a/libs/hwui/jni/GIFMovie.cpp b/libs/hwui/jni/GIFMovie.cpp index fef51b8d2f79..ae6ac4ce4ecc 100644 --- a/libs/hwui/jni/GIFMovie.cpp +++ b/libs/hwui/jni/GIFMovie.cpp @@ -7,9 +7,11 @@ #include "Movie.h" +#include "SkBitmap.h" #include "SkColor.h" #include "SkColorPriv.h" #include "SkStream.h" +#include "SkTypes.h" #include "gif_lib.h" diff --git a/libs/hwui/jni/Graphics.cpp b/libs/hwui/jni/Graphics.cpp index 33669ac0a34e..6a3bc8fe1152 100644 --- a/libs/hwui/jni/Graphics.cpp +++ b/libs/hwui/jni/Graphics.cpp @@ -8,10 +8,18 @@ #include <nativehelper/JNIHelp.h> #include "GraphicsJNI.h" +#include "include/private/SkTemplates.h" // SkTAddOffset +#include "SkBitmap.h" #include "SkCanvas.h" +#include "SkColorSpace.h" #include "SkFontMetrics.h" +#include "SkImageInfo.h" #include "SkMath.h" +#include "SkPixelRef.h" +#include "SkPoint.h" +#include "SkRect.h" #include "SkRegion.h" +#include "SkTypes.h" #include <cutils/ashmem.h> #include <hwui/Canvas.h> diff --git a/libs/hwui/jni/ImageDecoder.cpp b/libs/hwui/jni/ImageDecoder.cpp index f7b8c014be6e..bad710dec274 100644 --- a/libs/hwui/jni/ImageDecoder.cpp +++ b/libs/hwui/jni/ImageDecoder.cpp @@ -29,8 +29,12 @@ #include <FrontBufferedStream.h> #include <SkAndroidCodec.h> -#include <SkEncodedImageFormat.h> +#include <SkBitmap.h> +#include <SkColorSpace.h> +#include <SkImageInfo.h> +#include <SkRect.h> #include <SkStream.h> +#include <SkString.h> #include <androidfw/Asset.h> #include <fcntl.h> diff --git a/libs/hwui/jni/Movie.h b/libs/hwui/jni/Movie.h index 736890d5215e..02113dd58ec8 100644 --- a/libs/hwui/jni/Movie.h +++ b/libs/hwui/jni/Movie.h @@ -13,6 +13,7 @@ #include "SkBitmap.h" #include "SkCanvas.h" #include "SkRefCnt.h" +#include "SkTypes.h" class SkStreamRewindable; diff --git a/libs/hwui/jni/MovieImpl.cpp b/libs/hwui/jni/MovieImpl.cpp index ae9e04e617b0..abb75fa99c94 100644 --- a/libs/hwui/jni/MovieImpl.cpp +++ b/libs/hwui/jni/MovieImpl.cpp @@ -5,11 +5,12 @@ * found in the LICENSE file. */ #include "Movie.h" -#include "SkCanvas.h" -#include "SkPaint.h" +#include "SkBitmap.h" +#include "SkStream.h" +#include "SkTypes.h" // We should never see this in normal operation since our time values are -// 0-based. So we use it as a sentinal. +// 0-based. So we use it as a sentinel. #define UNINITIALIZED_MSEC ((SkMSec)-1) Movie::Movie() @@ -81,8 +82,6 @@ const SkBitmap& Movie::bitmap() //////////////////////////////////////////////////////////////////// -#include "SkStream.h" - Movie* Movie::DecodeMemory(const void* data, size_t length) { SkMemoryStream stream(data, length, false); return Movie::DecodeStream(&stream); diff --git a/libs/hwui/jni/NinePatch.cpp b/libs/hwui/jni/NinePatch.cpp index 08fc80fbdafd..d50a8a22b5cb 100644 --- a/libs/hwui/jni/NinePatch.cpp +++ b/libs/hwui/jni/NinePatch.cpp @@ -24,8 +24,10 @@ #include <hwui/Paint.h> #include <utils/Log.h> +#include "SkBitmap.h" #include "SkCanvas.h" #include "SkLatticeIter.h" +#include "SkRect.h" #include "SkRegion.h" #include "GraphicsJNI.h" #include "NinePatchPeeker.h" diff --git a/libs/hwui/jni/NinePatchPeeker.cpp b/libs/hwui/jni/NinePatchPeeker.cpp index 9171fc687276..d85ede5dc6d2 100644 --- a/libs/hwui/jni/NinePatchPeeker.cpp +++ b/libs/hwui/jni/NinePatchPeeker.cpp @@ -16,7 +16,7 @@ #include "NinePatchPeeker.h" -#include <SkBitmap.h> +#include <SkScalar.h> #include <cutils/compiler.h> using namespace android; diff --git a/libs/hwui/jni/Paint.cpp b/libs/hwui/jni/Paint.cpp index f76863255153..0aa14655725c 100644 --- a/libs/hwui/jni/Paint.cpp +++ b/libs/hwui/jni/Paint.cpp @@ -26,6 +26,7 @@ #include <nativehelper/ScopedPrimitiveArray.h> #include "SkColorFilter.h" +#include "SkColorSpace.h" #include "SkFont.h" #include "SkFontMetrics.h" #include "SkFontTypes.h" diff --git a/libs/hwui/jni/Shader.cpp b/libs/hwui/jni/Shader.cpp index 0bbd8a8cf97c..fa8e2e79c831 100644 --- a/libs/hwui/jni/Shader.cpp +++ b/libs/hwui/jni/Shader.cpp @@ -2,11 +2,21 @@ #define LOG_TAG "ShaderJNI" #include "GraphicsJNI.h" +#include "SkBitmap.h" +#include "SkBlendMode.h" +#include "SkColor.h" #include "SkColorFilter.h" #include "SkGradientShader.h" +#include "SkImage.h" #include "SkImagePriv.h" +#include "SkMatrix.h" +#include "SkPoint.h" +#include "SkRefCnt.h" +#include "SkSamplingOptions.h" +#include "SkScalar.h" #include "SkShader.h" -#include "SkBlendMode.h" +#include "SkString.h" +#include "SkTileMode.h" #include "include/effects/SkRuntimeEffect.h" #include <vector> @@ -16,7 +26,7 @@ using namespace android::uirenderer; /** * By default Skia gradients will interpolate their colors in unpremul space * and then premultiply each of the results. We must set this flag to preserve - * backwards compatiblity by premultiplying the colors of the gradient first, + * backwards compatibility by premultiplying the colors of the gradient first, * and then interpolating between them. */ static const uint32_t sGradientShaderFlags = SkGradientShader::kInterpolateColorsInPremul_Flag; diff --git a/libs/hwui/jni/Utils.h b/libs/hwui/jni/Utils.h index 6cdf44d85a5a..f6e3a0eeaa0e 100644 --- a/libs/hwui/jni/Utils.h +++ b/libs/hwui/jni/Utils.h @@ -17,8 +17,11 @@ #ifndef _ANDROID_GRAPHICS_UTILS_H_ #define _ANDROID_GRAPHICS_UTILS_H_ +#include "SkRefCnt.h" #include "SkStream.h" +class SkData; + #include <jni.h> #include <androidfw/Asset.h> diff --git a/libs/hwui/jni/YuvToJpegEncoder.cpp b/libs/hwui/jni/YuvToJpegEncoder.cpp index 77f42ae70268..87eda7e9f96f 100644 --- a/libs/hwui/jni/YuvToJpegEncoder.cpp +++ b/libs/hwui/jni/YuvToJpegEncoder.cpp @@ -1,5 +1,7 @@ #include "CreateJavaOutputStreamAdaptor.h" #include "SkJPEGWriteUtility.h" +#include "SkStream.h" +#include "SkTypes.h" #include "YuvToJpegEncoder.h" #include <ui/PixelFormat.h> #include <hardware/hardware.h> diff --git a/libs/hwui/jni/YuvToJpegEncoder.h b/libs/hwui/jni/YuvToJpegEncoder.h index 7e7b935df276..a69726b17e9d 100644 --- a/libs/hwui/jni/YuvToJpegEncoder.h +++ b/libs/hwui/jni/YuvToJpegEncoder.h @@ -1,13 +1,13 @@ #ifndef _ANDROID_GRAPHICS_YUV_TO_JPEG_ENCODER_H_ #define _ANDROID_GRAPHICS_YUV_TO_JPEG_ENCODER_H_ -#include "SkTypes.h" -#include "SkStream.h" extern "C" { #include "jpeglib.h" #include "jerror.h" } +class SkWStream; + class YuvToJpegEncoder { public: /** Create an encoder based on the YUV format. diff --git a/libs/hwui/jni/android_graphics_Canvas.cpp b/libs/hwui/jni/android_graphics_Canvas.cpp index 0ef80ee10708..61bb66557adc 100644 --- a/libs/hwui/jni/android_graphics_Canvas.cpp +++ b/libs/hwui/jni/android_graphics_Canvas.cpp @@ -32,10 +32,22 @@ #include "FontUtils.h" #include "Bitmap.h" +#include "SkBitmap.h" +#include "SkBlendMode.h" +#include "SkClipOp.h" +#include "SkColor.h" +#include "SkColorSpace.h" #include "SkGraphics.h" +#include "SkImageInfo.h" +#include "SkMatrix.h" +#include "SkPath.h" +#include "SkPoint.h" +#include "SkRect.h" +#include "SkRefCnt.h" #include "SkRegion.h" -#include "SkVertices.h" #include "SkRRect.h" +#include "SkScalar.h" +#include "SkVertices.h" namespace minikin { class MeasuredText; diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp index c48448dffdd2..55b1f23d294a 100644 --- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp +++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp @@ -23,8 +23,16 @@ #include <Picture.h> #include <Properties.h> #include <RootRenderNode.h> +#include <SkBitmap.h> +#include <SkColorSpace.h> +#include <SkData.h> +#include <SkImage.h> #include <SkImagePriv.h> +#include <SkPicture.h> +#include <SkPixmap.h> #include <SkSerialProcs.h> +#include <SkStream.h> +#include <SkTypeface.h> #include <dlfcn.h> #include <gui/TraceUtils.h> #include <inttypes.h> @@ -451,7 +459,7 @@ struct PictureCaptureState { }; // TODO: This & Multi-SKP & Single-SKP should all be de-duped into -// a single "make a SkPicture serailizable-safe" utility somewhere +// a single "make a SkPicture serializable-safe" utility somewhere class PictureWrapper : public Picture { public: PictureWrapper(sk_sp<SkPicture>&& src, const std::shared_ptr<PictureCaptureState>& state) diff --git a/libs/hwui/jni/fonts/Font.cpp b/libs/hwui/jni/fonts/Font.cpp index 09be630dc741..2c421f8727a8 100644 --- a/libs/hwui/jni/fonts/Font.cpp +++ b/libs/hwui/jni/fonts/Font.cpp @@ -22,7 +22,10 @@ #include "SkFont.h" #include "SkFontMetrics.h" #include "SkFontMgr.h" +#include "SkRect.h" #include "SkRefCnt.h" +#include "SkScalar.h" +#include "SkStream.h" #include "SkTypeface.h" #include "GraphicsJNI.h" #include <nativehelper/ScopedUtfChars.h> diff --git a/libs/hwui/pipeline/skia/DumpOpsCanvas.h b/libs/hwui/pipeline/skia/DumpOpsCanvas.h index 3f89c0712407..6a052dbb7cea 100644 --- a/libs/hwui/pipeline/skia/DumpOpsCanvas.h +++ b/libs/hwui/pipeline/skia/DumpOpsCanvas.h @@ -19,6 +19,8 @@ #include "RenderNode.h" #include "SkiaDisplayList.h" +class SkRRect; + namespace android { namespace uirenderer { namespace skiapipeline { diff --git a/libs/hwui/pipeline/skia/HolePunch.h b/libs/hwui/pipeline/skia/HolePunch.h index 92c6f7721a08..d0e1ca35049a 100644 --- a/libs/hwui/pipeline/skia/HolePunch.h +++ b/libs/hwui/pipeline/skia/HolePunch.h @@ -17,7 +17,6 @@ #pragma once #include <string> -#include "SkRRect.h" namespace android { namespace uirenderer { diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp index 507d3dcdcde9..3bf2b2e63a47 100644 --- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp +++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp @@ -15,7 +15,11 @@ */ #include "RenderNodeDrawable.h" +#include <SkPaint.h> #include <SkPaintFilterCanvas.h> +#include <SkPoint.h> +#include <SkRRect.h> +#include <SkRect.h> #include <gui/TraceUtils.h> #include "RenderNode.h" #include "SkiaDisplayList.h" diff --git a/libs/hwui/pipeline/skia/ShaderCache.cpp b/libs/hwui/pipeline/skia/ShaderCache.cpp index e7432ac5f216..ef3f1ca3c41d 100644 --- a/libs/hwui/pipeline/skia/ShaderCache.cpp +++ b/libs/hwui/pipeline/skia/ShaderCache.cpp @@ -16,6 +16,7 @@ #include "ShaderCache.h" #include <GrDirectContext.h> +#include <SkData.h> #include <gui/TraceUtils.h> #include <log/log.h> #include <openssl/sha.h> diff --git a/libs/hwui/pipeline/skia/ShaderCache.h b/libs/hwui/pipeline/skia/ShaderCache.h index 4dcc9fb49802..dd57d428ba31 100644 --- a/libs/hwui/pipeline/skia/ShaderCache.h +++ b/libs/hwui/pipeline/skia/ShaderCache.h @@ -17,12 +17,15 @@ #pragma once #include <GrContextOptions.h> +#include <SkRefCnt.h> #include <cutils/compiler.h> #include <memory> #include <mutex> #include <string> #include <vector> +class SkData; + namespace android { class BlobCache; @@ -45,7 +48,7 @@ public: * and puts the ShaderCache into an initialized state, such that it is * able to insert and retrieve entries from the cache. If identity is * non-null and validation fails, the cache is initialized but contains - * no data. If size is less than zero, the cache is initilaized but + * no data. If size is less than zero, the cache is initialized but * contains no data. * * This should be called when HWUI pipeline is initialized. When not in diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp index bc386feb2d6f..c546adaaf779 100644 --- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp @@ -16,15 +16,25 @@ #include "SkiaPipeline.h" +#include <SkCanvas.h> +#include <SkColor.h> +#include <SkColorSpace.h> +#include <SkData.h> +#include <SkImage.h> #include <SkImageEncoder.h> #include <SkImageInfo.h> #include <SkImagePriv.h> +#include <SkMatrix.h> #include <SkMultiPictureDocument.h> #include <SkOverdrawCanvas.h> #include <SkOverdrawColorFilter.h> #include <SkPicture.h> #include <SkPictureRecorder.h> +#include <SkRect.h> +#include <SkRefCnt.h> #include <SkSerialProcs.h> +#include <SkStream.h> +#include <SkString.h> #include <SkTypeface.h> #include <android-base/properties.h> #include <unistd.h> diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.h b/libs/hwui/pipeline/skia/SkiaPipeline.h index bc8a5659dd83..7887d1ae2117 100644 --- a/libs/hwui/pipeline/skia/SkiaPipeline.h +++ b/libs/hwui/pipeline/skia/SkiaPipeline.h @@ -16,14 +16,16 @@ #pragma once -#include <SkSurface.h> +#include <SkColorSpace.h> #include <SkDocument.h> #include <SkMultiPictureDocument.h> +#include <SkSurface.h> #include "Lighting.h" #include "hwui/AnimatedImageDrawable.h" #include "renderthread/CanvasContext.h" #include "renderthread/IRenderPipeline.h" +class SkFILEWStream; class SkPictureRecorder; struct SkSharingSerialContext; diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp index 9c51e628e04a..5c6117d86415 100644 --- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp +++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp @@ -16,7 +16,20 @@ #include "SkiaRecordingCanvas.h" #include "hwui/Paint.h" +#include <include/private/SkTemplates.h> // SkAutoSTMalloc +#include <SkBlendMode.h> +#include <SkData.h> +#include <SkDrawable.h> +#include <SkImage.h> #include <SkImagePriv.h> +#include <SkMatrix.h> +#include <SkPaint.h> +#include <SkPoint.h> +#include <SkRect.h> +#include <SkRefCnt.h> +#include <SkRRect.h> +#include <SkSamplingOptions.h> +#include <SkTypes.h> #include "CanvasTransform.h" #ifdef __ANDROID__ // Layoutlib does not support Layers #include "Layer.h" diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h index 1445a27e4248..89e3a2c24e1e 100644 --- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h +++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h @@ -22,6 +22,11 @@ #include "SkiaDisplayList.h" #include "pipeline/skia/AnimatedDrawables.h" +class SkBitmap; +class SkMatrix; +class SkPaint; +class SkRRect; + namespace android { namespace uirenderer { namespace skiapipeline { diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h index 56d42e013f31..a721be3c60d1 100644 --- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h +++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h @@ -22,6 +22,11 @@ #include "renderstate/RenderState.h" +#include "SkRefCnt.h" + +class SkBitmap; +struct SkRect; + namespace android { namespace uirenderer { namespace skiapipeline { diff --git a/libs/hwui/pipeline/skia/TransformCanvas.cpp b/libs/hwui/pipeline/skia/TransformCanvas.cpp index 41e36874b862..33160d05e2d0 100644 --- a/libs/hwui/pipeline/skia/TransformCanvas.cpp +++ b/libs/hwui/pipeline/skia/TransformCanvas.cpp @@ -19,6 +19,10 @@ #include "HolePunch.h" #include "SkData.h" #include "SkDrawable.h" +#include "SkMatrix.h" +#include "SkPaint.h" +#include "SkRect.h" +#include "SkRRect.h" using namespace android::uirenderer::skiapipeline; diff --git a/libs/hwui/pipeline/skia/TransformCanvas.h b/libs/hwui/pipeline/skia/TransformCanvas.h index 685b71d017e9..15f0c1abc55a 100644 --- a/libs/hwui/pipeline/skia/TransformCanvas.h +++ b/libs/hwui/pipeline/skia/TransformCanvas.h @@ -19,6 +19,13 @@ #include "SkPaintFilterCanvas.h" #include <effects/StretchEffect.h> +class SkData; +class SkDrawable; +class SkMatrix; +class SkPaint; +enum class SkBlendMode; +struct SkRect; + class TransformCanvas : public SkPaintFilterCanvas { public: TransformCanvas(SkCanvas* target, SkBlendMode blendmode) : diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h index fc6b28d2e1ad..b8f8c9267ad8 100644 --- a/libs/hwui/renderthread/EglManager.h +++ b/libs/hwui/renderthread/EglManager.h @@ -18,6 +18,7 @@ #include <EGL/egl.h> #include <EGL/eglext.h> +#include <SkColorSpace.h> #include <SkImageInfo.h> #include <SkRect.h> #include <cutils/compiler.h> diff --git a/libs/hwui/renderthread/IRenderPipeline.h b/libs/hwui/renderthread/IRenderPipeline.h index aceb5a528fc8..0238889ef78f 100644 --- a/libs/hwui/renderthread/IRenderPipeline.h +++ b/libs/hwui/renderthread/IRenderPipeline.h @@ -24,6 +24,7 @@ #include "hwui/Bitmap.h" #include "ColorMode.h" +#include <SkColorSpace.h> #include <SkRect.h> #include <utils/RefBase.h> diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index a44b498c81c1..b2ba15cbe526 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -29,6 +29,10 @@ #include "utils/Macros.h" #include "utils/TimeUtils.h" +#include <SkBitmap.h> +#include <SkImage.h> +#include <SkPicture.h> + #include <pthread.h> namespace android { diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h index ee9efd46e307..bbfeeac19d94 100644 --- a/libs/hwui/renderthread/RenderProxy.h +++ b/libs/hwui/renderthread/RenderProxy.h @@ -17,7 +17,7 @@ #ifndef RENDERPROXY_H_ #define RENDERPROXY_H_ -#include <SkBitmap.h> +#include <SkRefCnt.h> #include <android/native_window.h> #include <cutils/compiler.h> #include <android/surface_control.h> @@ -30,6 +30,10 @@ #include "SwapBehavior.h" #include "hwui/Bitmap.h" +class SkBitmap; +class SkPicture; +class SkImage; + namespace android { class GraphicBuffer; class Surface; diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp index 01b956cb3dd5..3ff4081726f3 100644 --- a/libs/hwui/renderthread/RenderThread.cpp +++ b/libs/hwui/renderthread/RenderThread.cpp @@ -266,7 +266,7 @@ void RenderThread::requireGlContext() { } mEglManager->initialize(); - sk_sp<const GrGLInterface> glInterface(GrGLCreateNativeInterface()); + sk_sp<const GrGLInterface> glInterface = GrGLMakeNativeInterface(); LOG_ALWAYS_FATAL_IF(!glInterface.get()); GrContextOptions options; diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h index b816649edf6e..cba210da3353 100644 --- a/libs/hwui/renderthread/VulkanManager.h +++ b/libs/hwui/renderthread/VulkanManager.h @@ -51,6 +51,9 @@ typedef void(VKAPI_PTR* PFN_vkFrameBoundaryANDROID)(VkDevice device, VkSemaphore #include "VulkanSurface.h" #include "private/hwui/DrawVkInfo.h" +#include <SkColorSpace.h> +#include <SkRefCnt.h> + class GrVkExtensions; namespace android { diff --git a/libs/hwui/renderthread/VulkanSurface.h b/libs/hwui/renderthread/VulkanSurface.h index beb71b727f51..26486669e712 100644 --- a/libs/hwui/renderthread/VulkanSurface.h +++ b/libs/hwui/renderthread/VulkanSurface.h @@ -20,6 +20,7 @@ #include <system/window.h> #include <vulkan/vulkan.h> +#include <SkColorSpace.h> #include <SkRefCnt.h> #include <SkSize.h> diff --git a/libs/hwui/tests/common/TestUtils.cpp b/libs/hwui/tests/common/TestUtils.cpp index 491af4336f97..a4890ede8faa 100644 --- a/libs/hwui/tests/common/TestUtils.cpp +++ b/libs/hwui/tests/common/TestUtils.cpp @@ -26,7 +26,13 @@ #include <renderthread/VulkanManager.h> #include <utils/Unicode.h> +#include "SkCanvas.h" #include "SkColorData.h" +#include "SkMatrix.h" +#include "SkPath.h" +#include "SkPixmap.h" +#include "SkRect.h" +#include "SkSurface.h" #include "SkUnPreMultiply.h" namespace android { diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h index 5092675a8104..75865c751d52 100644 --- a/libs/hwui/tests/common/TestUtils.h +++ b/libs/hwui/tests/common/TestUtils.h @@ -27,10 +27,20 @@ #include <renderstate/RenderState.h> #include <renderthread/RenderThread.h> +#include <SkBitmap.h> +#include <SkColor.h> +#include <SkImageInfo.h> +#include <SkRefCnt.h> + #include <gtest/gtest.h> #include <memory> #include <unordered_map> +class SkCanvas; +class SkMatrix; +class SkPath; +struct SkRect; + namespace android { namespace uirenderer { diff --git a/libs/hwui/tests/common/scenes/BitmapShaders.cpp b/libs/hwui/tests/common/scenes/BitmapShaders.cpp index 03aeb55f129b..a07cdf720b50 100644 --- a/libs/hwui/tests/common/scenes/BitmapShaders.cpp +++ b/libs/hwui/tests/common/scenes/BitmapShaders.cpp @@ -14,7 +14,17 @@ * limitations under the License. */ -#include <SkImagePriv.h> +#include <SkBitmap.h> +#include <SkBlendMode.h> +#include <SkCanvas.h> +#include <SkImage.h> +#include <SkImageInfo.h> +#include <SkPaint.h> +#include <SkRect.h> +#include <SkRefCnt.h> +#include <SkSamplingOptions.h> +#include <SkShader.h> +#include <SkTileMode.h> #include "hwui/Paint.h" #include "TestSceneBase.h" #include "tests/common/BitmapAllocationTestUtils.h" diff --git a/libs/hwui/tests/common/scenes/HwBitmap565.cpp b/libs/hwui/tests/common/scenes/HwBitmap565.cpp index cbdb756b8fa7..de0ef6d595f8 100644 --- a/libs/hwui/tests/common/scenes/HwBitmap565.cpp +++ b/libs/hwui/tests/common/scenes/HwBitmap565.cpp @@ -18,6 +18,12 @@ #include "tests/common/BitmapAllocationTestUtils.h" #include "utils/Color.h" +#include <SkBitmap.h> +#include <SkBlendMode.h> +#include <SkCanvas.h> +#include <SkPaint.h> +#include <SkRefCnt.h> + class HwBitmap565; static TestScene::Registrar _HwBitmap565(TestScene::Info{ diff --git a/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp b/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp index 564354f04674..0d5ca6df9ff3 100644 --- a/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp +++ b/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp @@ -17,6 +17,7 @@ #include "TestSceneBase.h" #include "utils/Color.h" +#include <SkColorSpace.h> #include <SkGradientShader.h> #include <SkImagePriv.h> #include <ui/PixelFormat.h> diff --git a/libs/hwui/tests/common/scenes/ListViewAnimation.cpp b/libs/hwui/tests/common/scenes/ListViewAnimation.cpp index d031923a112b..4a5d9468cd88 100644 --- a/libs/hwui/tests/common/scenes/ListViewAnimation.cpp +++ b/libs/hwui/tests/common/scenes/ListViewAnimation.cpp @@ -17,7 +17,16 @@ #include "TestSceneBase.h" #include "tests/common/TestListViewSceneBase.h" #include "hwui/Paint.h" +#include <SkBitmap.h> +#include <SkCanvas.h> +#include <SkColor.h> #include <SkFont.h> +#include <SkFontTypes.h> +#include <SkPaint.h> +#include <SkPoint.h> +#include <SkRect.h> +#include <SkRefCnt.h> +#include <SkScalar.h> #include <cstdio> class ListViewAnimation; @@ -48,7 +57,7 @@ class ListViewAnimation : public TestListViewSceneBase { 128 * 3; paint.setColor(bgDark ? Color::White : Color::Grey_700); - SkFont font; + SkFont font; font.setSize(size / 2); char charToShow = 'A' + (rand() % 26); const SkPoint pos = {SkIntToScalar(size / 2), diff --git a/libs/hwui/tests/common/scenes/MagnifierAnimation.cpp b/libs/hwui/tests/common/scenes/MagnifierAnimation.cpp index edadf78db051..070a339a86a1 100644 --- a/libs/hwui/tests/common/scenes/MagnifierAnimation.cpp +++ b/libs/hwui/tests/common/scenes/MagnifierAnimation.cpp @@ -19,6 +19,10 @@ #include "utils/Color.h" #include "hwui/Paint.h" +#include <SkBitmap.h> +#include <SkBlendMode.h> +#include <SkFont.h> + class MagnifierAnimation; static TestScene::Registrar _Magnifier(TestScene::Info{ diff --git a/libs/hwui/tests/common/scenes/ReadbackFromHardwareBitmap.cpp b/libs/hwui/tests/common/scenes/ReadbackFromHardwareBitmap.cpp index 716d3979bdcb..3caaf8236d8a 100644 --- a/libs/hwui/tests/common/scenes/ReadbackFromHardwareBitmap.cpp +++ b/libs/hwui/tests/common/scenes/ReadbackFromHardwareBitmap.cpp @@ -16,6 +16,12 @@ #include "TestSceneBase.h" +#include <SkBitmap.h> +#include <SkCanvas.h> +#include <SkPaint.h> +#include <SkRect.h> +#include <SkRefCnt.h> + class ReadbackFromHardware; static TestScene::Registrar _SaveLayer(TestScene::Info{ diff --git a/libs/hwui/tests/common/scenes/RecentsAnimation.cpp b/libs/hwui/tests/common/scenes/RecentsAnimation.cpp index 1c2507867f6e..27948f8b4b43 100644 --- a/libs/hwui/tests/common/scenes/RecentsAnimation.cpp +++ b/libs/hwui/tests/common/scenes/RecentsAnimation.cpp @@ -17,6 +17,11 @@ #include "TestSceneBase.h" #include "utils/Color.h" +#include <SkBitmap.h> +#include <SkBlendMode.h> +#include <SkColor.h> +#include <SkRefCnt.h> + class RecentsAnimation; static TestScene::Registrar _Recents(TestScene::Info{ diff --git a/libs/hwui/tests/common/scenes/StretchyListViewAnimation.cpp b/libs/hwui/tests/common/scenes/StretchyListViewAnimation.cpp index e677549b7894..59230a754f4e 100644 --- a/libs/hwui/tests/common/scenes/StretchyListViewAnimation.cpp +++ b/libs/hwui/tests/common/scenes/StretchyListViewAnimation.cpp @@ -14,7 +14,15 @@ * limitations under the License. */ +#include <SkBitmap.h> +#include <SkCanvas.h> +#include <SkColor.h> #include <SkFont.h> +#include <SkFontTypes.h> +#include <SkPaint.h> +#include <SkPoint.h> +#include <SkRefCnt.h> +#include <SkRRect.h> #include <cstdio> #include "TestSceneBase.h" #include "hwui/Paint.h" diff --git a/libs/hwui/tests/common/scenes/TvApp.cpp b/libs/hwui/tests/common/scenes/TvApp.cpp index c6219c485b85..aff8ca1e26c7 100644 --- a/libs/hwui/tests/common/scenes/TvApp.cpp +++ b/libs/hwui/tests/common/scenes/TvApp.cpp @@ -14,7 +14,12 @@ * limitations under the License. */ +#include "SkBitmap.h" #include "SkBlendMode.h" +#include "SkColorFilter.h" +#include "SkFont.h" +#include "SkImageInfo.h" +#include "SkRefCnt.h" #include "TestSceneBase.h" #include "tests/common/BitmapAllocationTestUtils.h" #include "hwui/Paint.h" diff --git a/libs/hwui/tests/unit/CanvasOpTests.cpp b/libs/hwui/tests/unit/CanvasOpTests.cpp index 2cf3456694b0..d2b1ef91a898 100644 --- a/libs/hwui/tests/unit/CanvasOpTests.cpp +++ b/libs/hwui/tests/unit/CanvasOpTests.cpp @@ -23,9 +23,17 @@ #include <tests/common/CallCountingCanvas.h> -#include "SkPictureRecorder.h" +#include "SkBitmap.h" +#include "SkCanvas.h" #include "SkColor.h" +#include "SkImageInfo.h" #include "SkLatticeIter.h" +#include "SkPaint.h" +#include "SkPath.h" +#include "SkPictureRecorder.h" +#include "SkRRect.h" +#include "SkRect.h" +#include "SkRegion.h" #include "pipeline/skia/AnimatedDrawables.h" #include <SkNoDrawCanvas.h> diff --git a/libs/hwui/tests/unit/EglManagerTests.cpp b/libs/hwui/tests/unit/EglManagerTests.cpp index 7f2e1589ae6c..ec9ab90fa46b 100644 --- a/libs/hwui/tests/unit/EglManagerTests.cpp +++ b/libs/hwui/tests/unit/EglManagerTests.cpp @@ -20,6 +20,8 @@ #include "renderthread/RenderEffectCapabilityQuery.h" #include "tests/common/TestContext.h" +#include <SkColorSpace.h> + using namespace android; using namespace android::uirenderer; using namespace android::uirenderer::renderthread; diff --git a/libs/hwui/tests/unit/FatalTestCanvas.h b/libs/hwui/tests/unit/FatalTestCanvas.h index 2a74afc5bb7a..96a0c6114682 100644 --- a/libs/hwui/tests/unit/FatalTestCanvas.h +++ b/libs/hwui/tests/unit/FatalTestCanvas.h @@ -19,6 +19,8 @@ #include <SkCanvas.h> #include <gtest/gtest.h> +class SkRRect; + namespace { class TestCanvasBase : public SkCanvas { diff --git a/libs/hwui/tests/unit/ShaderCacheTests.cpp b/libs/hwui/tests/unit/ShaderCacheTests.cpp index 87981f115763..105fea408736 100644 --- a/libs/hwui/tests/unit/ShaderCacheTests.cpp +++ b/libs/hwui/tests/unit/ShaderCacheTests.cpp @@ -25,6 +25,8 @@ #include <cstdint> #include "FileBlobCache.h" #include "pipeline/skia/ShaderCache.h" +#include <SkData.h> +#include <SkRefCnt.h> using namespace android::uirenderer::skiapipeline; diff --git a/libs/hwui/tests/unit/SkiaBehaviorTests.cpp b/libs/hwui/tests/unit/SkiaBehaviorTests.cpp index dc1b2e668dd0..c1ddbd36bcfd 100644 --- a/libs/hwui/tests/unit/SkiaBehaviorTests.cpp +++ b/libs/hwui/tests/unit/SkiaBehaviorTests.cpp @@ -16,9 +16,14 @@ #include "tests/common/TestUtils.h" +#include <SkBitmap.h> +#include <SkBlendMode.h> +#include <SkColor.h> #include <SkColorMatrixFilter.h> #include <SkColorSpace.h> -#include <SkImagePriv.h> +#include <SkImageInfo.h> +#include <SkPaint.h> +#include <SkPath.h> #include <SkPathOps.h> #include <SkShader.h> #include <gtest/gtest.h> diff --git a/libs/hwui/tests/unit/SkiaCanvasTests.cpp b/libs/hwui/tests/unit/SkiaCanvasTests.cpp index dae3c9435712..50d9f5683a8b 100644 --- a/libs/hwui/tests/unit/SkiaCanvasTests.cpp +++ b/libs/hwui/tests/unit/SkiaCanvasTests.cpp @@ -18,6 +18,7 @@ #include <hwui/Paint.h> #include <SkCanvasStateUtils.h> +#include <SkColorSpace.h> #include <SkPicture.h> #include <SkPictureRecorder.h> #include <gtest/gtest.h> diff --git a/libs/hwui/tests/unit/SkiaRenderPropertiesTests.cpp b/libs/hwui/tests/unit/SkiaRenderPropertiesTests.cpp index 15ecf5831f3a..ced667eb76e5 100644 --- a/libs/hwui/tests/unit/SkiaRenderPropertiesTests.cpp +++ b/libs/hwui/tests/unit/SkiaRenderPropertiesTests.cpp @@ -17,6 +17,7 @@ #include <VectorDrawable.h> #include <gtest/gtest.h> +#include <SkCanvas.h> #include <SkClipStack.h> #include <SkSurface_Base.h> #include <string.h> diff --git a/libs/hwui/tests/unit/TypefaceTests.cpp b/libs/hwui/tests/unit/TypefaceTests.cpp index ab23448ab93f..9295a938f397 100644 --- a/libs/hwui/tests/unit/TypefaceTests.cpp +++ b/libs/hwui/tests/unit/TypefaceTests.cpp @@ -21,8 +21,11 @@ #include <sys/stat.h> #include <utils/Log.h> +#include "SkData.h" #include "SkFontMgr.h" +#include "SkRefCnt.h" #include "SkStream.h" +#include "SkTypeface.h" #include "hwui/MinikinSkia.h" #include "hwui/Typeface.h" diff --git a/libs/hwui/tests/unit/VectorDrawableTests.cpp b/libs/hwui/tests/unit/VectorDrawableTests.cpp index 6d4c57413f00..c1c21bd7dfbf 100644 --- a/libs/hwui/tests/unit/VectorDrawableTests.cpp +++ b/libs/hwui/tests/unit/VectorDrawableTests.cpp @@ -21,6 +21,12 @@ #include "utils/MathUtils.h" #include "utils/VectorDrawableUtils.h" +#include <SkBitmap.h> +#include <SkCanvas.h> +#include <SkPath.h> +#include <SkRefCnt.h> +#include <SkShader.h> + #include <functional> namespace android { diff --git a/libs/input/MouseCursorController.cpp b/libs/input/MouseCursorController.cpp index 45da008c3e8e..956101e7a2a4 100644 --- a/libs/input/MouseCursorController.cpp +++ b/libs/input/MouseCursorController.cpp @@ -24,12 +24,6 @@ #include <log/log.h> -#include <SkBitmap.h> -#include <SkBlendMode.h> -#include <SkCanvas.h> -#include <SkColor.h> -#include <SkPaint.h> - namespace { // Time to spend fading out the pointer completely. const nsecs_t POINTER_FADE_DURATION = 500 * 1000000LL; // 500 ms diff --git a/libs/input/SpriteController.cpp b/libs/input/SpriteController.cpp index 2b809eab4ae4..a5ca49847bb6 100644 --- a/libs/input/SpriteController.cpp +++ b/libs/input/SpriteController.cpp @@ -249,8 +249,7 @@ void SpriteController::doUpdateSprites() { // Pass cursor metadata in the sprite surface so that when Android is running as a // client OS (e.g. ARC++) the host OS can get the requested cursor metadata and // update mouse cursor in the host OS. - t.setMetadata( - update.state.surfaceControl, METADATA_MOUSE_CURSOR, p); + t.setMetadata(update.state.surfaceControl, gui::METADATA_MOUSE_CURSOR, p); } int32_t surfaceLayer = mOverlayLayer + update.state.layer; diff --git a/libs/input/TouchSpotController.cpp b/libs/input/TouchSpotController.cpp index f7c685ff8ba6..4ac66c4ffb6a 100644 --- a/libs/input/TouchSpotController.cpp +++ b/libs/input/TouchSpotController.cpp @@ -23,12 +23,6 @@ #include <log/log.h> -#include <SkBitmap.h> -#include <SkBlendMode.h> -#include <SkCanvas.h> -#include <SkColor.h> -#include <SkPaint.h> - namespace { // Time to spend fading out the spot completely. const nsecs_t SPOT_FADE_DURATION = 200 * 1000000LL; // 200 ms diff --git a/media/aidl/android/media/audio/common/AudioPort.aidl b/media/aidl/android/media/audio/common/AudioPort.aidl index 84675e3a00a6..d32b840ebfe8 100644 --- a/media/aidl/android/media/audio/common/AudioPort.aidl +++ b/media/aidl/android/media/audio/common/AudioPort.aidl @@ -23,8 +23,9 @@ import android.media.audio.common.AudioProfile; import android.media.audio.common.ExtraAudioDescriptor; /** - * Audio port structure describes the capabilities of an audio port - * as well as its current configuration. + * Audio port structure describes the capabilities of an audio port. + * This is a "blueprint" which contains all the possible configurations + * that are supported by the port. * * {@hide} */ diff --git a/media/aidl/android/media/audio/common/AudioPortExt.aidl b/media/aidl/android/media/audio/common/AudioPortExt.aidl index c4681cbb182e..eadc0ab7c7c5 100644 --- a/media/aidl/android/media/audio/common/AudioPortExt.aidl +++ b/media/aidl/android/media/audio/common/AudioPortExt.aidl @@ -34,6 +34,9 @@ union AudioPortExt { AudioPortDeviceExt device; /** Information specific to mix ports. */ AudioPortMixExt mix; - /** Audio session identifier. */ + /** + * NOT USED. Framework audio session identifier. + * Use android.media.AudioPortExtSys.session on the system side. + */ int session; } diff --git a/media/aidl/android/media/audio/common/AudioPortMixExt.aidl b/media/aidl/android/media/audio/common/AudioPortMixExt.aidl index f3613a4ae31f..eb117eca52bd 100644 --- a/media/aidl/android/media/audio/common/AudioPortMixExt.aidl +++ b/media/aidl/android/media/audio/common/AudioPortMixExt.aidl @@ -32,12 +32,12 @@ parcelable AudioPortMixExt { AudioPortMixExtUseCase usecase; /** * Maximum number of input or output streams that can be simultaneously - * opened for this port. + * opened for this port. '0' means 'unlimited'. */ int maxOpenStreamCount; /** * Maximum number of input or output streams that can be simultaneously - * active for this port. + * active for this port. '0' means 'all opened streams'. */ int maxActiveStreamCount; /** Mute duration while changing device, when used for output. */ diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index e7eda3ea4552..2c68273f86e7 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -1636,8 +1636,10 @@ public class AudioManager { * * @param on set <var>true</var> to turn on speakerphone; * <var>false</var> to turn it off + * @deprecated Use {@link AudioManager#setCommunicationDevice(AudioDeviceInfo)} or + * {@link AudioManager#clearCommunicationDevice()} instead. */ - public void setSpeakerphoneOn(boolean on){ + @Deprecated public void setSpeakerphoneOn(boolean on) { final IAudioService service = getService(); try { service.setSpeakerphoneOn(mICallBack, on); @@ -1650,8 +1652,9 @@ public class AudioManager { * Checks whether the speakerphone is on or off. * * @return true if speakerphone is on, false if it's off + * @deprecated Use {@link AudioManager#getCommunicationDevice()} instead. */ - public boolean isSpeakerphoneOn() { + @Deprecated public boolean isSpeakerphoneOn() { final IAudioService service = getService(); try { return service.isSpeakerphoneOn(); @@ -2717,8 +2720,9 @@ public class AudioManager { * connection is established. * @see #stopBluetoothSco() * @see #ACTION_SCO_AUDIO_STATE_UPDATED + * @deprecated Use {@link AudioManager#setCommunicationDevice(AudioDeviceInfo)} instead. */ - public void startBluetoothSco(){ + @Deprecated public void startBluetoothSco() { final IAudioService service = getService(); try { service.startBluetoothSco(mICallBack, @@ -2761,9 +2765,10 @@ public class AudioManager { * bluetooth SCO audio with {@link #startBluetoothSco()} when finished with the SCO * connection or if connection fails. * @see #startBluetoothSco() + * @deprecated Use {@link AudioManager#clearCommunicationDevice()} instead. */ // Also used for connections started with {@link #startBluetoothScoVirtualCall()} - public void stopBluetoothSco(){ + @Deprecated public void stopBluetoothSco() { final IAudioService service = getService(); try { service.stopBluetoothSco(mICallBack); @@ -2795,8 +2800,9 @@ public class AudioManager { * * @return true if SCO is used for communications; * false if otherwise + * @deprecated Use {@link AudioManager#getCommunicationDevice()} instead. */ - public boolean isBluetoothScoOn() { + @Deprecated public boolean isBluetoothScoOn() { final IAudioService service = getService(); try { return service.isBluetoothScoOn(); diff --git a/media/java/android/media/audiofx/Visualizer.java b/media/java/android/media/audiofx/Visualizer.java index 3349277ede3b..ea4027eab158 100644 --- a/media/java/android/media/audiofx/Visualizer.java +++ b/media/java/android/media/audiofx/Visualizer.java @@ -110,10 +110,18 @@ public class Visualizer { public static final int MEASUREMENT_MODE_NONE = 0; /** - * Defines a measurement mode which computes the peak and RMS value in mB, where 0mB is the - * maximum sample value, and -9600mB is the minimum value. - * Values for peak and RMS can be retrieved with - * {@link #getMeasurementPeakRms(MeasurementPeakRms)}. + * Defines a measurement mode which computes the peak and RMS value in mB below the + * "full scale", where 0mB is normally the maximum sample value (but see the note + * below). Minimum value depends on the resolution of audio samples used by the audio + * framework. The value of -9600mB is the minimum value for 16-bit audio systems and + * -14400mB or below for "high resolution" systems. Values for peak and RMS can be + * retrieved with {@link #getMeasurementPeakRms(MeasurementPeakRms)}. + * + * <p class=note><strong>Note:</strong> when Visualizer effect is attached to the + * global session (with session ID 0), it is possible to observe RMS peaks higher than + * 0 dBFS, for example in the case when there are multiple audio sources playing + * simultaneously. In this case {@link #getMeasurementPeakRms(MeasurementPeakRms)} + * method can return a positive value. */ public static final int MEASUREMENT_MODE_PEAK_RMS = 1 << 0; diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java index 149c2f471a4c..04d28e7ddd91 100644 --- a/media/java/android/media/tv/TvInputManager.java +++ b/media/java/android/media/tv/TvInputManager.java @@ -60,7 +60,6 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Iterator; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Objects; @@ -484,7 +483,7 @@ public final class TvInputManager { private final Object mLock = new Object(); // @GuardedBy("mLock") - private final List<TvInputCallbackRecord> mCallbackRecords = new LinkedList<>(); + private final List<TvInputCallbackRecord> mCallbackRecords = new ArrayList<>(); // A mapping from TV input ID to the state of corresponding input. // @GuardedBy("mLock") diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppManager.java b/media/java/android/media/tv/interactive/TvInteractiveAppManager.java index 43d4605209dc..88ca30ceb8a6 100755 --- a/media/java/android/media/tv/interactive/TvInteractiveAppManager.java +++ b/media/java/android/media/tv/interactive/TvInteractiveAppManager.java @@ -50,8 +50,8 @@ import com.android.internal.util.Preconditions; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; import java.util.Iterator; -import java.util.LinkedList; import java.util.List; import java.util.concurrent.Executor; @@ -302,7 +302,7 @@ public final class TvInteractiveAppManager { new SparseArray<>(); // @GuardedBy("mLock") - private final List<TvInteractiveAppCallbackRecord> mCallbackRecords = new LinkedList<>(); + private final List<TvInteractiveAppCallbackRecord> mCallbackRecords = new ArrayList<>(); // A sequence number for the next session to be created. Should be protected by a lock // {@code mSessionCallbackRecordMap}. diff --git a/media/jni/Android.bp b/media/jni/Android.bp index 18b779fa7c57..e3e200fcd754 100644 --- a/media/jni/Android.bp +++ b/media/jni/Android.bp @@ -129,6 +129,7 @@ cc_library_shared { cc_library_shared { name: "libmedia_jni_utils", srcs: [ + ":libgui_frame_event_aidl", "android_media_Utils.cpp", ], diff --git a/native/android/surface_control.cpp b/native/android/surface_control.cpp index 1ebdc273931b..c2afc609e947 100644 --- a/native/android/surface_control.cpp +++ b/native/android/surface_control.cpp @@ -80,7 +80,7 @@ ASurfaceControl* ASurfaceControl_createFromWindow(ANativeWindow* window, const c Surface* surface = static_cast<Surface*>(window); sp<IBinder> parentHandle = surface->getSurfaceControlHandle(); - uint32_t flags = ISurfaceComposerClient::eFXSurfaceBufferState; + int32_t flags = ISurfaceComposerClient::eFXSurfaceBufferState; sp<SurfaceControl> surfaceControl; if (parentHandle) { surfaceControl = @@ -88,11 +88,8 @@ ASurfaceControl* ASurfaceControl_createFromWindow(ANativeWindow* window, const c // Format is only relevant for buffer queue layers. PIXEL_FORMAT_UNKNOWN /* format */, flags, parentHandle); } else { - surfaceControl = - client->createWithSurfaceParent(String8(debug_name), 0 /* width */, 0 /* height */, - // Format is only relevant for buffer queue layers. - PIXEL_FORMAT_UNKNOWN /* format */, flags, - static_cast<Surface*>(window)); + // deprecated, this should no longer be used + surfaceControl = nullptr; } if (!surfaceControl) { @@ -669,6 +666,8 @@ void ASurfaceTransaction_setFrameTimeline(ASurfaceTransaction* aSurfaceTransacti AVsyncId vsyncId) { CHECK_NOT_NULL(aSurfaceTransaction); const auto startTime = AChoreographer_getStartTimeNanosForVsyncId(vsyncId); - ASurfaceTransaction_to_Transaction(aSurfaceTransaction) - ->setFrameTimelineInfo({.vsyncId = vsyncId, .startTimeNanos = startTime}); + FrameTimelineInfo ftInfo; + ftInfo.vsyncId = vsyncId; + ftInfo.startTimeNanos = startTime; + ASurfaceTransaction_to_Transaction(aSurfaceTransaction)->setFrameTimelineInfo(ftInfo); } diff --git a/native/graphics/jni/imagedecoder.cpp b/native/graphics/jni/imagedecoder.cpp index bb25274e3136..cd6ed2391608 100644 --- a/native/graphics/jni/imagedecoder.cpp +++ b/native/graphics/jni/imagedecoder.cpp @@ -25,6 +25,12 @@ #include <hwui/ImageDecoder.h> #include <log/log.h> #include <SkAndroidCodec.h> +#include <SkCodec.h> +#include <SkColorSpace.h> +#include <SkImageInfo.h> +#include <SkRect.h> +#include <SkSize.h> +#include <SkStream.h> #include <utils/Color.h> #include <fcntl.h> diff --git a/packages/CompanionDeviceManager/AndroidManifest.xml b/packages/CompanionDeviceManager/AndroidManifest.xml index 8b5d214f7a10..c1fce7c3dd23 100644 --- a/packages/CompanionDeviceManager/AndroidManifest.xml +++ b/packages/CompanionDeviceManager/AndroidManifest.xml @@ -48,6 +48,14 @@ android:permission="android.permission.BIND_COMPANION_DEVICE_MANAGER_SERVICE" android:theme="@style/ChooserActivity"/> + <activity + android:name=".CompanionDeviceDataTransferActivity" + android:exported="true" + android:launchMode="singleInstance" + android:excludeFromRecents="true" + android:permission="android.permission.BIND_COMPANION_DEVICE_MANAGER_SERVICE" + android:theme="@style/ChooserActivity"/> + <service android:name=".CompanionDeviceDiscoveryService" android:exported="false" /> diff --git a/packages/CompanionDeviceManager/res/values-af/strings.xml b/packages/CompanionDeviceManager/res/values-af/strings.xml index 2d8ef7348dfd..bb3f987c67ca 100644 --- a/packages/CompanionDeviceManager/res/values-af/strings.xml +++ b/packages/CompanionDeviceManager/res/values-af/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Kies \'n <xliff:g id="PROFILE_NAME">%1$s</xliff:g> om deur <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> bestuur te word"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> sal interaksie met jou kennisgewings mag hê en toegang kry tot jou Foon-, SMS-, Kontakte- en Kalender-toestemmings."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> sal interaksie met jou kennisgewings mag hê en toegang kry tot jou Foon-, SMS-, Kontakte- en Kalender-toestemmings."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Laat <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> toe om programme te stroom?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Gee <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> afstandtoegang tot programme wat op <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> geïnstalleer is wanneer hierdie foon aan die internet gekoppel is."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Gee <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> afstandtoegang tot programme wat op <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> geïnstalleer is wanneer hierdie tablet aan die internet gekoppel is."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Gee <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> afstandtoegang tot programme wat op <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> geïnstalleer is wanneer hierdie toestel aan die internet gekoppel is."</string> + <string name="permission_apps" msgid="6142133265286656158">"Programme"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Stroom jou foon se programme"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Gee <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> toegang tot hierdie inligting op jou foon"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Oorkruistoestel-dienste"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> versoek tans namens jou <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> toegang tot jou foon se foto\'s, media en kennisgewings"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Gee <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> toegang tot hierdie inligting op jou foon"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Kennisgewings"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Kan alle kennisgewings lees, insluitend inligting soos kontakte, boodskappe en foto\'s"</string> + <string name="permission_storage" msgid="6831099350839392343">"Foto\'s en media"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play Dienste"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> versoek tans namens jou <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> toestemming om programme tussen jou toestelle te stroom"</string> <string name="profile_name_generic" msgid="6851028682723034988">"toestel"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Laat toe"</string> <string name="consent_no" msgid="2640796915611404382">"Moenie toelaat nie"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Dra programtoestemmings na jou horlosie toe oor"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Om dit makliker te maak om jou horlosie op te stel, sal programme wat gedurende opstelling op jou horlosie geïnstalleer word, dieselfde toestemmings as jou foon gebruik.\n\n Hierdie toestemmings kan toegang tot jou horlosie se mikrofoon en ligging insluit."</string> + <string name="consent_back" msgid="2560683030046918882">"Terug"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Gee programme op <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> dieselfde toestemmings as op <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Dit kan mikrofoon-, kamera- en liggingtoegang insluit, asook ander sensitiewe toestemmings op <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Jy kan hierdie toestemmings enige tyd verander in jou Instellings op <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-am/strings.xml b/packages/CompanionDeviceManager/res/values-am/strings.xml index 5cb306f14380..5c72a16b56c9 100644 --- a/packages/CompanionDeviceManager/res/values-am/strings.xml +++ b/packages/CompanionDeviceManager/res/values-am/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"በ<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> የሚተዳደር <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ይምረጡ"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ከማሳወቂያዎችዎ ጋር መስተጋብር እንዲፈጥር እና የእርስዎን ስልክ፣ ኤስኤምኤስ፣ እውቂያዎች እና የቀን መቁጠሪያ ፈቃዶች እንዲደርስ ይፈቀድለታል።"</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ከማሳወቂያዎችዎ ጋር መስተጋብር እንዲፈጥር እና የእርስዎን ስልክ፣ ኤስኤምኤስ፣ እውቂያዎች እና የቀን መቁጠሪያ ፈቃዶች እንዲደርስ ይፈቀድለታል።"</string> - <string name="title_app_streaming" msgid="4459136600249308574">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> መተግበሪያዎችን እንዲለቅቅ ይፈቀድለት?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ሲገናኙ በዚህ ስልክ ላይ የተጫኑ መተግበሪያዎችን እንዲደርስ ለ<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> የርቀት መዳረሻ እንዲያቀርብ ይፍቀዱለት።"</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ሲገናኙ በዚህ ጡባዊ ላይ የተጫኑ መተግበሪያዎችን እንዲደርስ ለ<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> የርቀት መዳረሻ እንዲያቀርብ ይፍቀዱለት።"</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ሲገናኙ በዚህ መሳሪያ ላይ የተጫኑ መተግበሪያዎችን እንዲደርስ ለ<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> የርቀት መዳረሻ እንዲያቀርብ ይፍቀዱለት።"</string> + <string name="permission_apps" msgid="6142133265286656158">"መተግበሪያዎች"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"የስልክዎን መተግበሪያዎች በዥረት ይልቀቁ"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ይህን መረጃ ከስልክዎ እንዲደርስበት ይፍቀዱለት"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"መሣሪያ ተሻጋሪ አገልግሎቶች"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> የእርስዎን ስልክ ፎቶዎች፣ ሚዲያ እና ማሳወቂያዎች ለመድረስ የእርስዎን <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ወክሎ ፈቃድ እየጠየቀ ነው"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ይህን መረጃ ከስልክዎ ላይ እንዲደርስ ይፍቀዱለት"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"ማሳወቂያዎች"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"እንደ እውቂያዎች፣ መልዕክቶች እና ፎቶዎች ያሉ መረጃዎችን ጨምሮ ሁሉንም ማሳወቂያዎች ማንበብ ይችላል"</string> + <string name="permission_storage" msgid="6831099350839392343">"ፎቶዎች እና ሚዲያ"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"የGoogle Play አገልግሎቶች"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> በእርስዎ መሣሪያዎች መካከል መተግበሪያዎችን በዥረት ለመልቀቅ የእርስዎን <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ወክሎ ፈቃድ እየጠየቀ ነው"</string> <string name="profile_name_generic" msgid="6851028682723034988">"መሣሪያ"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"ፍቀድ"</string> <string name="consent_no" msgid="2640796915611404382">"አትፍቀድ"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"የመተግበሪያ ፈቃዶችን ወደ የእጅ ሰዓትዎ ያስተላልፉ"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"የእጅ ሰዓትዎን ማቀናበርን ለማቅለል በማዋቀር ጊዜ በእጅ ሰዓትዎ ላይ የተጫኑ መተግበሪያዎች እንደ ስልክዎ ተመሳሳይ ፈቃዶችን ይጠቀማሉ።\n\n እነዚህ ፈቃዶች የእጅ ሰዓትዎ ማይክሮፎን እና አካባቢ መዳረሻን ሊያካትቱ ይችላሉ።"</string> + <string name="consent_back" msgid="2560683030046918882">"ተመለስ"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"በ<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> ላይ ላሉ መተግበሪያዎች በ<strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> ላይ ካሉት ጋር ተመሳሳይ ፈቃዶች ይሰጣቸው?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>ይህ የማይክሮፎን፣ የካሜራ እና የአካባቢ መዳረሻ እና ሌሎች በ<strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p> ላይ ያሉ አደገኛ ፈቃዶችን ሊያካትት ይችላል።እነዚህን ፈቃዶች በማንኛውም ጊዜ በ<strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>ላይ ቅንብሮችዎ ውስጥ መቀየር ይችላሉ።"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-ar/strings.xml b/packages/CompanionDeviceManager/res/values-ar/strings.xml index b4c74ad07e40..f3313c93be64 100644 --- a/packages/CompanionDeviceManager/res/values-ar/strings.xml +++ b/packages/CompanionDeviceManager/res/values-ar/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"اختَر <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ليديره تطبيق <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"سيتم السماح لتطبيق <xliff:g id="APP_NAME">%1$s</xliff:g> بالتفاعل مع الإشعارات والوصول إلى أذونات الهاتف والرسائل القصيرة وجهات الاتصال والتقويم."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"سيتم السماح لتطبيق <xliff:g id="APP_NAME">%1$s</xliff:g> بالتفاعل مع الإشعارات والوصول إلى أذونات الهاتف والرسائل القصيرة وجهات الاتصال والتقويم."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"هل تريد السماح لتطبيق <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ببث التطبيقات؟"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"السماح لتطبيق <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> بمنح الإذن بالوصول عن بُعد إلى التطبيقات المثبَّتة <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> الإذن بالوصول عن بُعد إلى التطبيقات المثبَّتة على هذا الهاتف عندما يكون متصلاً بالإنترنت."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"السماح لتطبيق <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> بمنح <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> الإذن بالوصول عن بُعد إلى التطبيقات المثبَّتة على هذا الجهاز اللوحي عندما يكون متصلاً بالإنترنت."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"السماح لتطبيق <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> بمنح <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> الإذن بالوصول عن بُعد إلى التطبيقات المثبَّتة على هذا الجهاز عندما يكون متصلاً بالإنترنت."</string> + <string name="permission_apps" msgid="6142133265286656158">"التطبيقات"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"بث تطبيقات هاتفك"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"السماح لتطبيق <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> بالوصول إلى هذه المعلومات من هاتفك"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"الخدمات التي تعمل بين الأجهزة"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"يطلب التطبيق <xliff:g id="APP_NAME">%1$s</xliff:g> الحصول على إذن نيابةً عن <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> للوصول إلى صور ووسائط وإشعارات هاتفك."</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"السماح لتطبيق <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> بالوصول إلى هذه المعلومات من هاتفك"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"الإشعارات"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"يمكن لهذا الملف الشخصي قراءة جميع الإشعارات، بما في ذلك المعلومات، مثل جهات الاتصال والرسائل والصور."</string> + <string name="permission_storage" msgid="6831099350839392343">"الصور والوسائط"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"خدمات Google Play"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"يطلب التطبيق <xliff:g id="APP_NAME">%1$s</xliff:g> الحصول على إذن نيابةً عن <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> لمشاركة التطبيقات بين أجهزتك."</string> <string name="profile_name_generic" msgid="6851028682723034988">"جهاز"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"السماح"</string> <string name="consent_no" msgid="2640796915611404382">"عدم السماح"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"نقل أذونات التطبيقات إلى ساعتك"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"لتسهيل إعداد ساعتك، فإن التطبيقات التي يتم تثبيتها على ساعتك أثناء الإعداد ستستخدم الأذونات نفسها التي يستخدمها هاتفك.\n\n قد تشتمل هذه الأذونات على الوصول إلى ميكروفون ساعتك وبيانات موقعها الجغرافي."</string> + <string name="consent_back" msgid="2560683030046918882">"رجوع"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"هل تريد منح التطبيقات على <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> نفس الأذونات على <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>؟"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>قد تتضمَّن هذه الأذونات الوصول إلى الميكروفون والكاميرا والموقع الجغرافي وغيرها من أذونات الوصول إلى المعلومات الحسّاسة على <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>يمكنك تغيير هذه الأذونات في أي وقت في إعداداتك على <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-as/strings.xml b/packages/CompanionDeviceManager/res/values-as/strings.xml index b2865dc79ad5..614260b3d55f 100644 --- a/packages/CompanionDeviceManager/res/values-as/strings.xml +++ b/packages/CompanionDeviceManager/res/values-as/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>এ পৰিচালনা কৰিব লগা এটা <xliff:g id="PROFILE_NAME">%1$s</xliff:g> বাছনি কৰক"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g>ক আপোনাৰ জাননী ব্যৱহাৰ কৰিবলৈ আৰু আপোনাৰ ফ’ন, এছএমএছ, সম্পৰ্ক আৰু কেলেণ্ডাৰৰ অনুমতি এক্সেছ কৰিবলৈ দিয়া হ’ব।"</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g>ক আপোনাৰ জাননী ব্যৱহাৰ কৰিবলৈ আৰু আপোনাৰ ফ’ন, এছএমএছ, সম্পৰ্ক আৰু কেলেণ্ডাৰৰ অনুমতি এক্সেছ কৰিবলৈ দিয়া হ’ব।"</string> - <string name="title_app_streaming" msgid="4459136600249308574">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ক এপ্লিকেশ্বন ষ্ট্ৰীম কৰিবলৈ অনুমতি দিবনে?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"সংযোগ কৰিলে <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ক এই ফ’নটোত ইনষ্টল কৰি থোৱা এপ্লিকেশ্বনসমূহ এক্সেছ কৰিবলৈ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>ক ৰিম’ট এক্সেছ দিবলৈ দিয়ক।"</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"সংযোগ কৰিলে <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ক এই টেবলেটটোত ইনষ্টল কৰি থোৱা এপ্লিকেশ্বনসমূহ এক্সেছ কৰিবলৈ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>ক ৰিম’ট এক্সেছ দিবলৈ দিয়ক।"</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"সংযোগ কৰিলে <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ক এই ডিভাইচটোত ইনষ্টল কৰি থোৱা এপ্লিকেশ্বনসমূহ এক্সেছ কৰিবলৈ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>ক ৰিম’ট এক্সেছ দিবলৈ দিয়ক।"</string> + <string name="permission_apps" msgid="6142133265286656158">"এপ্"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"আপোনাৰ ফ’নৰ এপ্ ষ্ট্ৰীম কৰক"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ক আপোনাৰ ফ’নৰ পৰা এই তথ্যখিনি এক্সেছ কৰাৰ অনুমতি দিয়ক"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"ক্ৰছ-ডিভাইচ সেৱাসমূহ"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ আপোনৰ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ৰ হৈ আপোনাৰ ফ’নৰ ফট’ মিডিয়া আৰু জাননী এক্সেছ কৰাৰ বাবে অনুৰোধ জনাইছে"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ক আপোনাৰ ফ’নৰ পৰা এই তথ্যখিনি এক্সেছ কৰাৰ অনুমতি দিয়ক"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"জাননী"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"সম্পৰ্কসূচী, বাৰ্তা আৰু ফট’ৰ দৰে তথ্যকে ধৰি আটাইবোৰ জাননী পঢ়িব পাৰে"</string> + <string name="permission_storage" msgid="6831099350839392343">"ফট’ আৰু মিডিয়া"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play সেৱা"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ আপোনৰ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ৰ হৈ আপোনাৰ ডিভাইচসমূহৰ মাজত এপ্ ষ্ট্ৰীম কৰাৰ বাবে অনুৰোধ জনাইছে"</string> <string name="profile_name_generic" msgid="6851028682723034988">"ডিভাইচ"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"অনুমতি দিয়ক"</string> <string name="consent_no" msgid="2640796915611404382">"অনুমতি নিদিব"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"আপোনাৰ ঘড়ীলৈ এপৰ অনুমতিসমূহ স্থানান্তৰ কৰক"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"আপোনাৰ ঘড়ীটো ছেটআপ কৰাটো অধিক সহজ কৰি তুলিবলৈ, এয়া কৰাৰ সময়ত আপোনাৰ ঘড়ীটোত ইনষ্টল কৰি থোৱা এপ্সমূহে আপোনাৰ ফ’নৰ দৰে একেই অনুমতিসমূহ ব্যৱহাৰ কৰিব।\n\n এই অনুমতিসমূহত আপোনাৰ ঘড়ীৰ মাইক্ৰ’ফ’ন আৰু অৱস্থানৰ এক্সেছ অন্তৰ্ভুক্ত হ’ব পাৰে।"</string> + <string name="consent_back" msgid="2560683030046918882">"উভতি যাওক"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"এপ্সমূহক <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>ত দিয়াৰ দৰে <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong>তো একে অনুমতি প্ৰদান কৰিবনে?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>ইয়াত <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>ত মাইক্ৰ’ফ’ন, কেমেৰা আৰু অৱস্থানৰ এক্সেছ আৰু অন্য সংবেদশীল অনুমতিসমূহ প্ৰদান কৰাটো অন্তৰ্ভুক্ত হ’ব পাৰে।</p> <p>আপুনি যিকোনো সময়তে <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>ত থকা আপোনাৰ ছেটিঙত এই অনুমতিসমূহ সলনি কৰিব পাৰে।</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-az/strings.xml b/packages/CompanionDeviceManager/res/values-az/strings.xml index e8e4e7631481..692b3a7adb9c 100644 --- a/packages/CompanionDeviceManager/res/values-az/strings.xml +++ b/packages/CompanionDeviceManager/res/values-az/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> tərəfindən idarə ediləcək <xliff:g id="PROFILE_NAME">%1$s</xliff:g> seçin"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> bildirişlərinizə, Telefon, SMS, Kontaktlar və Təqvimə giriş əldə edəcək."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> bildirişlərinizə, Telefon, SMS, Kontaktlar və Təqvimə giriş əldə edəcək."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tətbiqinin tətbiqlərdə yayım etməsinə icazə verilsin?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tətbiqinə <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> cihazının qoşulduqda bu telefonda quraşdırılmış tətbiqlərə uzaqdan giriş icazəsi verməsinə imkan verin."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tətbiqinə <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> cihazının qoşulduqda bu planşetdə quraşdırılmış tətbiqlərə uzaqdan giriş icazəsi verməsinə imkan verin."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tətbiqinə <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> cihazının qoşulduqda bu cihazda quraşdırılmış tətbiqlərə uzaqdan giriş icazəsi verməsinə imkan verin."</string> + <string name="permission_apps" msgid="6142133265286656158">"Tətbiqlər"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Telefonunuzun tətbiqlərini yayımlayın"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tətbiqinə telefonunuzdan bu məlumata giriş icazəsi verin"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cihazlararası xidmətlər"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> tətbiqi <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> adından telefonunuzun fotoları, mediası və bildirişlərinə giriş üçün icazə istəyir"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tətbiqinə telefonunuzdan bu məlumata giriş icazəsi verin"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Bildirişlər"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Bütün bildirişləri, o cümlədən kontaktlar, mesajlar və fotolar kimi məlumatları oxuya bilər"</string> + <string name="permission_storage" msgid="6831099350839392343">"Foto və media"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play xidmətləri"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> tətbiqi <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> adından cihazlarınız arasında tətbiqləri yayımlamaq üçün icazə istəyir"</string> <string name="profile_name_generic" msgid="6851028682723034988">"cihaz"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"İcazə verin"</string> <string name="consent_no" msgid="2640796915611404382">"İcazə verməyin"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Tətbiq icazələrini saatınıza köçürün"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Saatınızı ayarlamağı asanlaşdırmaq üçün ayarlama zamanı saatınızda quraşdırılmış tətbiqlər telefonunuzla eyni icazələrdən istifadə edəcək.\n\n Bu icazələrə saatınızın mikrofonuna və məkanına giriş daxil ola bilər."</string> + <string name="consent_back" msgid="2560683030046918882">"Geriyə"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> cihazındakı tətbiqlərə <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> cihazındakılarla eyni icazələr verilsin?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Buraya <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> cihazındakı Mikrofon, Kamera və Məkana girişi və digər həssas icazələr daxil ola bilər.</p> <p>Bu icazələri istənilən vaxt <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> cihazında ayarlarınızda dəyişə bilərsiniz.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml b/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml index 5d98a13e660e..09fa46562f6f 100644 --- a/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml +++ b/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Odaberite profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kojim će upravljati aplikacija <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> će dobiti dozvolu za interakciju sa obaveštenjima i pristup dozvolama za telefon, SMS poruke, kontakte i kalendar."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> će dobiti dozvolu za interakciju sa obaveštenjima i pristup dozvolama za telefon, SMS poruke, kontakte i kalendar."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Želite da dozvolite aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da strimuje aplikacije?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Dozvolite aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da daljinski pristupa aplikacijama instaliranim na telefonu <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> kada je povezan."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Dozvolite aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da daljinski pristupa aplikacijama instaliranim na tabletu <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> kada je povezan."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Dozvolite aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da daljinski pristupa aplikacijama instaliranim na uređaju <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> kada je povezan."</string> + <string name="permission_apps" msgid="6142133265286656158">"Aplikacije"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Strimujte aplikacije na telefonu"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Dozvolite da <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pristupa ovim informacijama sa telefona"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Usluge na više uređaja"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> zahteva dozvolu u ime uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> za pristup slikama, medijskom sadržaju i obaveštenjima sa telefona"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Dozvolite da <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pristupa ovim informacijama sa telefona"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Obaveštenja"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Može da čita sva obaveštenja, uključujući informacije poput kontakata, poruka i slika"</string> + <string name="permission_storage" msgid="6831099350839392343">"Slike i mediji"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play usluge"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> zahteva dozvolu u ime uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> za strimovanje aplikacija između uređaja"</string> <string name="profile_name_generic" msgid="6851028682723034988">"uređaj"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Dozvoli"</string> <string name="consent_no" msgid="2640796915611404382">"Ne dozvoli"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Prenesite dozvole za aplikacije na sat"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Da bismo pojednostavili podešavanje sata, aplikacije instalirane na satu tokom podešavanja će koristiti iste dozvole kao telefon.\n\n Te dozvole mogu da obuhvataju pristup mikrofonu i lokaciji sata."</string> + <string name="consent_back" msgid="2560683030046918882">"Nazad"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Aplikcijama na uređaju <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> dajte sve dozvole kao na uređaju <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>To može da obuhvata pristup mikrofonu, kameri i lokaciji, kao i drugim osetljivim dozvolama na uređaju <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>U svakom trenutku možete da promenite te dozvole u Podešavanjima na uređaju <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-be/strings.xml b/packages/CompanionDeviceManager/res/values-be/strings.xml index 3a57bcc34fb6..882699e0caaf 100644 --- a/packages/CompanionDeviceManager/res/values-be/strings.xml +++ b/packages/CompanionDeviceManager/res/values-be/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Выберыце прыладу (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>), якой будзе кіраваць праграма <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> атрымае доступ да вашых апавяшчэнняў, тэлефона, SMS, кантактаў і календара."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> атрымае доступ да вашых апавяшчэнняў, тэлефона, SMS, кантактаў і календара."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Дазволіць праграме <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> перадаваць праграмы плынню?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Дазвольце праграме <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> атрымліваць аддалены доступ да праграм, усталяваных на тэлефоне <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> (калі тэлефон падключаны)."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Дазвольце праграме <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> атрымліваць аддалены доступ да праграм, усталяваных на планшэце <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> (калі планшэт падключаны)."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Дазвольце праграме <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> атрымліваць аддалены доступ да праграм, усталяваных на прыладзе <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> (калі прылада падключана)."</string> + <string name="permission_apps" msgid="6142133265286656158">"Праграмы"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Трансліруйце змесціва праграм з вашага тэлефона"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Дазвольце праграме <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> мець доступ да гэтай інфармацыі з вашага тэлефона"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Сэрвісы для некалькіх прылад"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> запытвае дазвол ад імя вашай прылады \"<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>\" на доступ да фота, медыяфайлаў і апавяшчэнняў вашага тэлефона"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Дазвольце праграме <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> мець доступ да гэтай інфармацыі з вашага тэлефона"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Апавяшчэнні"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Можа счытваць усе апавяшчэнні, уключаючы паведамленні, фота і інфармацыю пра кантакты"</string> + <string name="permission_storage" msgid="6831099350839392343">"Фота і медыяфайлы"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Сэрвісы Google Play"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> запытвае дазвол ад імя вашай прылады \"<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>\" на перадачу праграм плынню паміж вашымі прыладамі"</string> <string name="profile_name_generic" msgid="6851028682723034988">"прылада"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Дазволіць"</string> <string name="consent_no" msgid="2640796915611404382">"Не дазваляць"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Перанос дазволаў праграм на ваш гадзіннік"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Для праграм, усталяваных на гадзіннік падчас наладжвання, будуць дзейнічаць тыя самыя дазволы, што і на тэлефоне.\n\n Так гадзіннік можа атрымаць доступ да мікрафона і даных пра месцазнаходжанне."</string> + <string name="consent_back" msgid="2560683030046918882">"Назад"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Даць праграмам на прыладзе <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> такія самыя дазволы, што і на прыладзе <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Дазволы могуць уключаць доступ да мікрафона, камеры і даных пра месцазнаходжанне, а таксама да іншай канфідэнцыяльнай інфармацыі на прыладзе <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Вы можаце ў любы час змяніць гэтыя дазволы ў Наладах на прыладзе <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-bg/strings.xml b/packages/CompanionDeviceManager/res/values-bg/strings.xml index d29a9081afc0..f55b950e922d 100644 --- a/packages/CompanionDeviceManager/res/values-bg/strings.xml +++ b/packages/CompanionDeviceManager/res/values-bg/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Изберете устройство (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>), което да се управлява от <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ще получи разрешение да взаимодейства с известията ви и да осъществява достъп до разрешенията за телефона, SMS съобщенията, контактите и календара."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ще получи разрешение да взаимодейства с известията ви и да осъществява достъп до разрешенията за телефона, SMS съобщенията, контактите и календара."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Разрешавате ли на <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да предава поточно приложения?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Разрешете на <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да предоставя на <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> отдалечен достъп до приложенията, инсталирани на този телефон, когато има установена връзка."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Разрешете на <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да предоставя на <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> отдалечен достъп до приложенията, инсталирани на този таблет, когато има установена връзка."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Разрешете на <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да предоставя на <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> отдалечен достъп до приложенията, инсталирани на това устройство, когато има установена връзка."</string> + <string name="permission_apps" msgid="6142133265286656158">"Приложения"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Поточно предаване на приложенията на телефона ви"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Разрешете на <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да осъществява достъп до тази информация от телефона ви"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Услуги за различни устройства"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> иска разрешение от името на <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> за достъп до снимките, мултимедията и известията на телефона ви"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Разрешете на <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да осъществява достъп до тази информация от телефона ви"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Известия"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Може да чете всички известия, включително различна информация, като например контакти, съобщения и снимки"</string> + <string name="permission_storage" msgid="6831099350839392343">"Снимки и мултимедия"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Услуги за Google Play"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> иска разрешение от името на <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> да предава поточно приложения между устройствата ви"</string> <string name="profile_name_generic" msgid="6851028682723034988">"устройство"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Разрешаване"</string> <string name="consent_no" msgid="2640796915611404382">"Забраняване"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Прехвърляне на разрешенията за приложенията към часовника"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"За по-лесно конфигуриране на часовника ви приложенията, инсталирани на него по време на настройването, ще използват същите разрешения като предоставените на телефона ви.\n\nТе може да включват достъп до микрофона и местоположението на часовника ви."</string> + <string name="consent_back" msgid="2560683030046918882">"Назад"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Искате ли да дадете на приложенията на <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> същите разрешения както на <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Това може да включва достъп до микрофона, камерата и местоположението, както и други разрешения за достъп до поверителна информация на <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Можете да промените тези разрешения по всяко време от настройките на <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-bn/strings.xml b/packages/CompanionDeviceManager/res/values-bn/strings.xml index 7d0b097f2a99..c38c17fcf100 100644 --- a/packages/CompanionDeviceManager/res/values-bn/strings.xml +++ b/packages/CompanionDeviceManager/res/values-bn/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"<xliff:g id="PROFILE_NAME">%1$s</xliff:g> বেছে নিন যেটি <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> ম্যানেজ করবে"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> আপনার বিজ্ঞপ্তির সাথে ইন্টার্যাক্ট করতে পারবে, তার সাথে আপনার ফোন, এমএসএস, পরিচিতি এবং ক্যালেন্ডারের অনুমতিও অ্যাক্সেস করতে পারবে।"</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> আপনার বিজ্ঞপ্তির সাথে ইন্টার্যাক্ট করতে পারবে, তার সাথে আপনার ফোন, এমএসএস, পরিচিতি এবং ক্যালেন্ডারের অনুমতিও অ্যাক্সেস করতে পারবে।"</string> - <string name="title_app_streaming" msgid="4459136600249308574">"অ্যাপ্লিকেশন স্ট্রিম করার জন্য <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> কে অনুমতি দেবেন?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> কে <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>এ দূরবর্তী অ্যাক্সেস প্রদান করতে দিন যাতে কানেক্ট থাকাকালীন এই ফোনে ইনস্টল করা অ্যাপ্লিকেশনগুলিতে অ্যাক্সেস করা যায়।"</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> কে <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>এ দূরবর্তী অ্যাক্সেস প্রদান করতে দিন যাতে কানেক্ট থাকাকালীন এই ট্যাবলেটে ইনস্টল করা অ্যাপ্লিকেশনগুলিতে অ্যাক্সেস করা যায়।"</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> কে <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>এ দূরবর্তী অ্যাক্সেস প্রদান করতে দিন যাতে কানেক্ট থাকাকালীন এই ডিভাইসে ইনস্টল করা অ্যাপ্লিকেশনগুলিতে অ্যাক্সেস করা যায়।"</string> + <string name="permission_apps" msgid="6142133265286656158">"অ্যাপ"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"আপনার ফোনের অ্যাপ স্ট্রিমিংয়ের মাধ্যমে কাস্ট করুন"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"আপনার ফোন থেকে <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> অ্যাপকে এই তথ্য অ্যাক্সেস করার অনুমতি দিন"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"ক্রস-ডিভাইস পরিষেবা"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"আপনার ফোনের ফটো, মিডিয়া এবং তথ্য অ্যাক্সেস করার জন্য <xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-এর হয়ে অনুমতি চাইছে"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"আপনার ফোন থেকে <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-কে এই তথ্য অ্যাক্সেস করার অনুমতি দিন"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"বিজ্ঞপ্তি"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"সব বিজ্ঞপ্তি পড়তে পারবে, যার মধ্যে পরিচিতি, মেসেজ ও ফটোর মতো তথ্য অন্তর্ভুক্ত"</string> + <string name="permission_storage" msgid="6831099350839392343">"ফটো ও মিডিয়া"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play পরিষেবা"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"আপনার ডিভাইসগুলির মধ্যে অ্যাপ স্ট্রিম করার জন্য <xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-এর হয়ে অনুমতি চাইছে"</string> <string name="profile_name_generic" msgid="6851028682723034988">"ডিভাইস"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"অনুমতি দিন"</string> <string name="consent_no" msgid="2640796915611404382">"অনুমতি দেবেন না"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"অ্যাপকে দেওয়া অনুমতি আপনার ঘড়িতে ট্রান্সফার করুন"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"ঘড়ি আরও সহজে সেট আপ করতে, সেট আপ চলাকালীন আপনার ঘড়িতে ইনস্টল করা অ্যাপ ফোনের মতো একই অনুমতি ব্যবহার করবে।\n\n এইসব অনুমতির মধ্যে আপনার ঘড়ির মাইক্রোফোন ও লোকেশন সম্পর্কে তথ্যের অ্যাক্সেস অন্তর্ভুক্ত থাকতে পারে।"</string> + <string name="consent_back" msgid="2560683030046918882">"ফিরুন"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>-এ যে অনুমতি দেওয়া আছে <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong>-এও সেই একই অনুমতি দিতে চান?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>এটি <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p&gt-এ হয়ত মাইক্রোফোন, ক্যামেরা এবং লোকেশনের অ্যাক্সেস ও অন্যান্য সংবেদনশীল অনুমতি অন্তর্ভুক্ত করতে পারে;আপনি যেকোনও সময় <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>-এর \'সেটিংস\'-এ গিয়ে এইসব অনুমতি পরিবর্তন করতে পারবেন"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-bs/strings.xml b/packages/CompanionDeviceManager/res/values-bs/strings.xml index a723da8f59a4..4957f92d9829 100644 --- a/packages/CompanionDeviceManager/res/values-bs/strings.xml +++ b/packages/CompanionDeviceManager/res/values-bs/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Odaberite uređaj <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kojim će upravljati aplikacija <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"Aplikaciji <xliff:g id="APP_NAME">%1$s</xliff:g> će se dozvoliti da ostvari interakciju s vašim obavještenjima i da pristupi odobrenjima za Telefon, SMS, Kontakte i Kalendar."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"Aplikaciji <xliff:g id="APP_NAME">%1$s</xliff:g> će se dozvoliti da ostvari interakciju s vašim obavještenjima i da pristupi odobrenjima za Telefon, SMS, Kontakte i Kalendar."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Dozvoliti da <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> prenosi aplikacije?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Dozvolite da <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> omogući daljinski pristup uređaju <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> radi pristupanja aplikacijama instaliranim na ovom telefonu kada je povezan s mrežom."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Dozvolite da <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> omogući daljinski pristup uređaju <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> radi pristupanja aplikacijama instaliranim na ovom tabletu kada je povezan s mrežom."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Dozvolite da <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> omogući daljinski pristup uređaju <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> radi pristupanja aplikacijama instaliranim na njemu kada je povezan s mrežom."</string> + <string name="permission_apps" msgid="6142133265286656158">"Aplikacije"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Prenosite aplikacije s telefona"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Dozvolite da aplikacija <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pristupa ovim informacijama s telefona"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Usluga na više uređaja"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> u ime uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> zahtijeva odobrenje da pristupi fotografijama, medijima i odobrenjima vašeg telefona"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> - <string name="title_computer" msgid="4693714143506569253">"Dozvolite da aplikacija <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pristupa ovim informacijama s vašeg telefona"</string> + <string name="title_computer" msgid="4693714143506569253">"Dozvolite aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da pristupa ovim informacijama s vašeg telefona"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Obavještenja"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Može čitati sva obavještenja, uključujući informacije kao što su kontakti, poruke i fotografije"</string> + <string name="permission_storage" msgid="6831099350839392343">"Fotografije i mediji"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play usluge"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> u ime uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> zahtijeva odobrenje da prenosi aplikacije između vaših uređaja"</string> <string name="profile_name_generic" msgid="6851028682723034988">"uređaj"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Dozvoli"</string> <string name="consent_no" msgid="2640796915611404382">"Nemoj dozvoliti"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Prijenos odobrenja za aplikaciju na sat"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Radi lakšeg postavljanja sata, aplikacije instalirane na satu tokom postavljanja će koristiti ista odobrenja kao i na telefonu.\n\n Ta odobrenja mogu uključivati pristup mikrofonu i lokaciji sata."</string> + <string name="consent_back" msgid="2560683030046918882">"Nazad"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Dati aplikacijama na uređaju <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> ista odobrenja kao na uređaju <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Ovo može uključivati pristup mikrofonu, kameri i lokaciji i druga osjetljiva odobrenja na uređaju <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Uvijek možete promijeniti ova odobrenja u Postavkama na uređaju <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-ca/strings.xml b/packages/CompanionDeviceManager/res/values-ca/strings.xml index de7e2256ede8..74b42e77bd6b 100644 --- a/packages/CompanionDeviceManager/res/values-ca/strings.xml +++ b/packages/CompanionDeviceManager/res/values-ca/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Tria un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> perquè el gestioni <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> tindrà permís per interaccionar amb les teves notificacions i accedir al telèfon, als SMS, als contactes i al calendari."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> tindrà permís per interaccionar amb les teves notificacions i accedir al telèfon, als SMS, als contactes i al calendari."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Vols permetre que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> reprodueixi aplicacions en continu?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Permet que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> proporcioni accés remot a <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> per accedir a les aplicacions instal·lades en aquest telèfon quan estigui connectat."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Permet que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> proporcioni accés remot a <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> per accedir a les aplicacions instal·lades en aquesta tauleta quan estigui connectada."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Permet que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> proporcioni accés remot a <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> per accedir a les aplicacions instal·lades en aquest dispositiu quan estigui connectat."</string> + <string name="permission_apps" msgid="6142133265286656158">"Aplicacions"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Reprodueix en continu aplicacions del telèfon"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Permet que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> accedeixi a aquesta informació del telèfon"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Serveis multidispositiu"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> demana permís en nom del teu dispositiu (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) per accedir a les fotos, el contingut multimèdia i les notificacions del telèfon"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Permet que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> accedeixi a aquesta informació del telèfon"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Notificacions"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Pot llegir totes les notificacions, inclosa informació com ara els contactes, els missatges i les fotos"</string> + <string name="permission_storage" msgid="6831099350839392343">"Fotos i contingut multimèdia"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Serveis de Google Play"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> demana permís en nom del teu dispositiu (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) per reproduir en continu aplicacions entre els dispositius"</string> <string name="profile_name_generic" msgid="6851028682723034988">"dispositiu"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Permet"</string> <string name="consent_no" msgid="2640796915611404382">"No permetis"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transfereix els permisos de les aplicacions al teu rellotge"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Per facilitar la configuració del rellotge, les aplicacions instal·lades al rellotge durant la configuració utilitzaran els mateixos permisos que al teu telèfon.\n\n Aquests permisos poden incloure l\'accés al micròfon i a la ubicació del rellotge."</string> + <string name="consent_back" msgid="2560683030046918882">"Enrere"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Vols concedir a les aplicacions del dispositiu <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> els mateixos permisos que tenen a <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Això pot incloure accés al micròfon, a la càmera i a la ubicació, i altres permisos sensibles a <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Pots canviar aquests permisos en qualsevol moment a <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>, a Configuració.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-cs/strings.xml b/packages/CompanionDeviceManager/res/values-cs/strings.xml index f195e54f743c..35414f05997f 100644 --- a/packages/CompanionDeviceManager/res/values-cs/strings.xml +++ b/packages/CompanionDeviceManager/res/values-cs/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Vyberte zařízení <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, které chcete spravovat pomocí aplikace <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> bude moci interagovat s vašimi oznámeními a získá přístup k telefonu, SMS, kontaktům a kalendáři."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> bude moci interagovat s vašimi oznámeními a získá přístup k telefonu, SMS, kontaktům a kalendáři."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Povolit aplikaci <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> streamovat aplikace?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Povolit aplikaci <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> poskytovat <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> vzdálený přístup k aplikacím nainstalovaným v tomto telefonu, když je připojen."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Povolit aplikaci <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> poskytovat <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> vzdálený přístup k aplikacím nainstalovaným v tomto tabletu, když je připojen."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Povolit aplikaci <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> poskytovat <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> vzdálený přístup k aplikacím nainstalovaným v tomto zařízení, když je připojeno."</string> + <string name="permission_apps" msgid="6142133265286656158">"Aplikace"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Streamujte aplikace v telefonu"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Povolte aplikaci <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> přístup k těmto informacím z vašeho telefonu"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Služby pro více zařízení"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> požaduje za vaše zařízení <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> oprávnění k přístupu k fotkám, médiím a oznámením v telefonu"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Povolte aplikaci <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> přístup k těmto informacím z vašeho telefonu"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Oznámení"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Může číst veškerá oznámení včetně informací, jako jsou kontakty, zprávy a fotky"</string> + <string name="permission_storage" msgid="6831099350839392343">"Fotky a média"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Služby Google Play"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> požaduje za vaše zařízení <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> oprávnění ke streamování aplikací mezi zařízeními"</string> <string name="profile_name_generic" msgid="6851028682723034988">"zařízení"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Povolit"</string> <string name="consent_no" msgid="2640796915611404382">"Nepovolovat"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Přesunout oprávnění aplikací do hodinek"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Abychom vám usnadnili nastavení hodinek, aplikace nainstalované do hodinek během úvodního nastavení budou používat stejná oprávnění jako váš telefon.\n\n Tato oprávnění mohou zahrnovat přístup k mikrofonu a poloze hodinek."</string> + <string name="consent_back" msgid="2560683030046918882">"Zpět"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Udělit aplikacím v zařízení <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> stejné oprávnění jako v zařízení <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Může být zahrnut přístup k mikrofonu, fotoaparátu a poloze a další citlivá oprávnění na zařízení <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Tato oprávnění můžete v Nastavení na zařízení <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> kdykoliv změnit.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-da/strings.xml b/packages/CompanionDeviceManager/res/values-da/strings.xml index a2aa5dddb43c..d9f0162e6e0a 100644 --- a/packages/CompanionDeviceManager/res/values-da/strings.xml +++ b/packages/CompanionDeviceManager/res/values-da/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Vælg den enhed (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>), som skal administreres af <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> får tilladelse til at interagere med dine notifikationer og adgang til dine tilladelser for Opkald, Sms, Kontakter og Kalender."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> får tilladelse til at interagere med dine notifikationer og adgang til dine tilladelser for Opkald, Sms, Kontakter og Kalender."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Vil du give <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tilladelse til at streame apps?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Giver <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tilladelse til at fjernstyre apps, som er installeret på <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>, når telefonen har forbindelse til internettet."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Giver <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tilladelse til at fjernstyre apps, som er installeret på <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>, når tabletten har forbindelse til internettet."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Giver <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tilladelse til at fjernstyre apps, som er installeret på <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>, når enheden har forbindelse til internettet."</string> + <string name="permission_apps" msgid="6142133265286656158">"Apps"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Stream din telefons apps"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Giv <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> adgang til disse oplysninger fra din telefon"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Tjenester, som kan tilsluttes en anden enhed"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> anmoder om tilladelse på vegne af din <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> til at få adgang til din telefons billeder, medier og notifikationer"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Tillad, at <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> får adgang til disse oplysninger fra din telefon"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Notifikationer"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Kan læse alle notifikationer, herunder oplysninger som f.eks. kontakter, beskeder og billeder"</string> + <string name="permission_storage" msgid="6831099350839392343">"Billeder og medier"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play-tjenester"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> anmoder om tilladelse på vegne af din <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> til at streame apps mellem dine enheder"</string> <string name="profile_name_generic" msgid="6851028682723034988">"enhed"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Tillad"</string> <string name="consent_no" msgid="2640796915611404382">"Tillad ikke"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Overfør apptilladelser til dit ur"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"For at gøre det nemmere at konfigurere dit ur vil de apps, der installeres under konfigurationen, anvende de samme tilladelser som din telefon.\n\n Disse tilladelser kan omfatte adgang til dit urs mikrofon og lokation."</string> + <string name="consent_back" msgid="2560683030046918882">"Tilbage"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Vil du give apps på <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> de samme tilladelser som på <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Dette kan omfatte mikrofon-, kamera- og lokationsadgang samt andre tilladelser til at tilgå følsomme oplysninger på <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Du kan til enhver tid ændre disse tilladelser under Indstillinger på <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-de/strings.xml b/packages/CompanionDeviceManager/res/values-de/strings.xml index 2b5ab117900e..9fed647ad64e 100644 --- a/packages/CompanionDeviceManager/res/values-de/strings.xml +++ b/packages/CompanionDeviceManager/res/values-de/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Gerät (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>) auswählen, das von <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> verwaltet werden soll"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> darf mit deinen Benachrichtigungen interagieren und auf die Berechtigungen „Telefon“, „SMS“, „Kontakte“ und „Kalender“ zugreifen."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> darf mit deinen Benachrichtigungen interagieren und auf die Berechtigungen „Telefon“, „SMS“, „Kontakte“ und „Kalender“ zugreifen."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Möchtest du <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> erlauben, Apps zu streamen?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Besteht eine Verbindung, darf <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> Remotezugriff auf die auf diesem Smartphone installierten Apps geben."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Besteht eine Verbindung, darf <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> Remotezugriff auf die auf diesem Tablet installierten Apps geben."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Besteht eine Verbindung, darf <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> Remotezugriff auf die auf diesem Gerät installierten Apps geben."</string> + <string name="permission_apps" msgid="6142133265286656158">"Apps"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Smartphone-Apps streamen"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> Zugriff auf diese Informationen von deinem Smartphone gewähren"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Geräteübergreifende Dienste"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> bittet im Namen deines <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> um die Berechtigung zum Zugriff auf die Fotos, Medien und Benachrichtigungen deines Smartphones"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> Zugriff auf diese Informationen von deinem Smartphone gewähren"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Benachrichtigungen"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Kann alle Benachrichtigungen lesen, einschließlich Informationen wie Kontakten, Nachrichten und Fotos"</string> + <string name="permission_storage" msgid="6831099350839392343">"Fotos und Medien"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play-Dienste"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> bittet im Namen deines <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> um die Berechtigung zum Streamen von Apps zwischen deinen Geräten"</string> <string name="profile_name_generic" msgid="6851028682723034988">"Gerät"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Zulassen"</string> <string name="consent_no" msgid="2640796915611404382">"Nicht zulassen"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"App-Berechtigungen auf Smartwatch übertragen"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Damit sich deine Smartwatch leichter einrichten lässt, erhalten die Apps, die während der Einrichtung auf deiner Smartwatch installiert werden, automatisch die gleichen Berechtigungen wie deine Smartphone-Apps.\n\n Zu diesen Berechtigungen kann der Zugriff auf das Mikrofon und den Standort deiner Smartwatch gehören."</string> + <string name="consent_back" msgid="2560683030046918882">"Zurück"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Apps auf <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> die gleichen Berechtigungen geben wie auf <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Dazu können Berechtigungen für Mikrofon, Kamera und Standortzugriff sowie andere vertrauliche Berechtigungen auf <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> gehören.</p><p>Sie lassen sich jederzeit in den Einstellungen auf <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> ändern.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-el/strings.xml b/packages/CompanionDeviceManager/res/values-el/strings.xml index 339f85a58127..2a26d5c1d55b 100644 --- a/packages/CompanionDeviceManager/res/values-el/strings.xml +++ b/packages/CompanionDeviceManager/res/values-el/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Επιλέξτε ένα προφίλ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> για διαχείριση από την εφαρμογή <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> θα επιτρέπεται να αλληλεπιδρά με τις ειδοποιήσεις σας και να έχει πρόσβαση στις άδειες Τηλεφώνου, SMS, Επαφών και Ημερολογίου."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> θα επιτρέπεται να αλληλεπιδρά με τις ειδοποιήσεις σας και να έχει πρόσβαση στις άδειες Τηλεφώνου, SMS, Επαφών και Ημερολογίου."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Να επιτρέπεται στην εφαρμογή <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> η ροή εφαρμογών;"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Επιτρέψτε στην εφαρμογή <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> να παρέχει απομακρυσμένη πρόσβαση στη συσκευή <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> κατά τη σύνδεση, προκειμένου να έχει πρόσβαση σε εφαρμογές που έχουν εγκατασταθεί σε αυτό το τηλέφωνο."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Επιτρέψτε στην εφαρμογή <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> να παρέχει απομακρυσμένη πρόσβαση στη συσκευή <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> κατά τη σύνδεση, προκειμένου να έχει πρόσβαση σε εφαρμογές που έχουν εγκατασταθεί σε αυτό το tablet."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Επιτρέψτε στην εφαρμογή <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> να παρέχει απομακρυσμένη πρόσβαση στη συσκευή <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> κατά τη σύνδεση, προκειμένου να έχει πρόσβαση σε εφαρμογές που έχουν εγκατασταθεί σε αυτήν τη συσκευή."</string> + <string name="permission_apps" msgid="6142133265286656158">"Εφαρμογές"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Μεταδώστε σε ροή τις εφαρμογές του τηλεφώνου σας"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Να επιτρέπεται στην εφαρμογή <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> η πρόσβαση σε αυτές τις πληροφορίες από το τηλέφωνό σας."</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Υπηρεσίες πολλών συσκευών"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> ζητά εκ μέρους της συσκευής σας <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> άδεια για πρόσβαση στις φωτογραφίες, τα αρχεία μέσων και τις ειδοποιήσεις του τηλεφώνου σας"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Επιτρέψτε στην εφαρμογή <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> να έχει πρόσβαση σε αυτές τις πληροφορίες από το τηλέφωνό σας"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Ειδοποιήσεις"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Μπορεί να διαβάσει όλες τις ειδοποιήσεις, συμπεριλαμβανομένων πληροφοριών όπως επαφές, μηνύματα και φωτογραφίες"</string> + <string name="permission_storage" msgid="6831099350839392343">"Φωτογραφίες και μέσα"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Υπηρεσίες Google Play"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> ζητά εκ μέρους της συσκευής σας <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> άδεια για ροή εφαρμογών μεταξύ των συσκευών σας"</string> <string name="profile_name_generic" msgid="6851028682723034988">"συσκευή"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Να επιτρέπεται"</string> <string name="consent_no" msgid="2640796915611404382">"Να μην επιτρέπεται"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Μεταφορά αδειών εφαρμογών στο ρολόι σας"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Για να είναι πιο εύκολη η ρύθμιση του ρολογιού σας, οι εφαρμογές που εγκαθίστανται στο ρολόι σας κατά τη ρύθμιση, θα χρησιμοποιούν τις ίδιες άδειες με το τηλέφωνό σας.\n\n Στις άδειες ενδέχεται να περιλαμβάνεται άδεια πρόσβασης στο μικρόφωνο και την τοποθεσία του ρολογιού σας."</string> + <string name="consent_back" msgid="2560683030046918882">"Πίσω"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Παραχώρηση στις εφαρμογές στη συσκευή <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> των ίδιων αδειών όπως στη συσκευή <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>;"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Αυτές μπορεί να περιλαμβάνουν πρόσβαση σε μικρόφωνο, κάμερα και τοποθεσία και άλλες άδειες πρόσβασης σε ευαίσθητες πληροφορίες στη συσκευή <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Μπορείτε να αλλάξετε αυτές τις άδειες ανά πάσα στιγμή στις Ρυθμίσεις σας στη συσκευή <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml b/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml index d59641111959..c4138ef0bae9 100644 --- a/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml +++ b/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts and Calendar permissions."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts and Calendar permissions."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to stream applications?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Let <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> provide <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> remote access to access to applications installed on this phone when connected."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Let <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> provide <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> remote access to access to applications installed on this tablet when connected."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Let <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> provide <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> remote access to access to applications installed on this device when connected."</string> + <string name="permission_apps" msgid="6142133265286656158">"Apps"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Stream your phone’s apps"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access this information from your phone"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to access your phone’s photos, media and notifications"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access this information from your phone"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Notifications"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Can read all notifications, including information like contacts, messages and photos"</string> + <string name="permission_storage" msgid="6831099350839392343">"Photos and media"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play services"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to stream apps between your devices"</string> <string name="profile_name_generic" msgid="6851028682723034988">"device"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Allow"</string> <string name="consent_no" msgid="2640796915611404382">"Don\'t allow"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transfer app permissions to your watch"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"To make it easier to set up your watch, apps installed on your watch during setup will use the same permissions as your phone.\n\n These permissions may include access to your watch’s microphone and location."</string> + <string name="consent_back" msgid="2560683030046918882">"Back"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Give apps on <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> the same permissions as on <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>This may include microphone, camera and location access, and other sensitive permissions on <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>You can change these permissions at any time in your settings on <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml b/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml index d59641111959..c4138ef0bae9 100644 --- a/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml +++ b/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts and Calendar permissions."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts and Calendar permissions."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to stream applications?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Let <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> provide <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> remote access to access to applications installed on this phone when connected."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Let <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> provide <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> remote access to access to applications installed on this tablet when connected."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Let <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> provide <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> remote access to access to applications installed on this device when connected."</string> + <string name="permission_apps" msgid="6142133265286656158">"Apps"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Stream your phone’s apps"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access this information from your phone"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to access your phone’s photos, media and notifications"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access this information from your phone"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Notifications"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Can read all notifications, including information like contacts, messages and photos"</string> + <string name="permission_storage" msgid="6831099350839392343">"Photos and media"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play services"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to stream apps between your devices"</string> <string name="profile_name_generic" msgid="6851028682723034988">"device"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Allow"</string> <string name="consent_no" msgid="2640796915611404382">"Don\'t allow"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transfer app permissions to your watch"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"To make it easier to set up your watch, apps installed on your watch during setup will use the same permissions as your phone.\n\n These permissions may include access to your watch’s microphone and location."</string> + <string name="consent_back" msgid="2560683030046918882">"Back"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Give apps on <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> the same permissions as on <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>This may include microphone, camera and location access, and other sensitive permissions on <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>You can change these permissions at any time in your settings on <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml b/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml index d59641111959..c4138ef0bae9 100644 --- a/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml +++ b/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts and Calendar permissions."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts and Calendar permissions."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to stream applications?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Let <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> provide <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> remote access to access to applications installed on this phone when connected."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Let <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> provide <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> remote access to access to applications installed on this tablet when connected."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Let <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> provide <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> remote access to access to applications installed on this device when connected."</string> + <string name="permission_apps" msgid="6142133265286656158">"Apps"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Stream your phone’s apps"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access this information from your phone"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to access your phone’s photos, media and notifications"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access this information from your phone"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Notifications"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Can read all notifications, including information like contacts, messages and photos"</string> + <string name="permission_storage" msgid="6831099350839392343">"Photos and media"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play services"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to stream apps between your devices"</string> <string name="profile_name_generic" msgid="6851028682723034988">"device"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Allow"</string> <string name="consent_no" msgid="2640796915611404382">"Don\'t allow"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transfer app permissions to your watch"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"To make it easier to set up your watch, apps installed on your watch during setup will use the same permissions as your phone.\n\n These permissions may include access to your watch’s microphone and location."</string> + <string name="consent_back" msgid="2560683030046918882">"Back"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Give apps on <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> the same permissions as on <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>This may include microphone, camera and location access, and other sensitive permissions on <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>You can change these permissions at any time in your settings on <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml b/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml index d59641111959..c4138ef0bae9 100644 --- a/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml +++ b/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts and Calendar permissions."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts and Calendar permissions."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to stream applications?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Let <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> provide <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> remote access to access to applications installed on this phone when connected."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Let <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> provide <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> remote access to access to applications installed on this tablet when connected."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Let <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> provide <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> remote access to access to applications installed on this device when connected."</string> + <string name="permission_apps" msgid="6142133265286656158">"Apps"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Stream your phone’s apps"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access this information from your phone"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to access your phone’s photos, media and notifications"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access this information from your phone"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Notifications"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Can read all notifications, including information like contacts, messages and photos"</string> + <string name="permission_storage" msgid="6831099350839392343">"Photos and media"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play services"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to stream apps between your devices"</string> <string name="profile_name_generic" msgid="6851028682723034988">"device"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Allow"</string> <string name="consent_no" msgid="2640796915611404382">"Don\'t allow"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transfer app permissions to your watch"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"To make it easier to set up your watch, apps installed on your watch during setup will use the same permissions as your phone.\n\n These permissions may include access to your watch’s microphone and location."</string> + <string name="consent_back" msgid="2560683030046918882">"Back"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Give apps on <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> the same permissions as on <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>This may include microphone, camera and location access, and other sensitive permissions on <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>You can change these permissions at any time in your settings on <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml b/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml index 9f17a89099d6..69a212aa9f98 100644 --- a/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml +++ b/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts and Calendar permissions."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts and Calendar permissions."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to stream applications?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Let <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to provide <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> remote access to access to applications installed on this phone when connected."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Let <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to provide <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> remote access to access to applications installed on this tablet when connected."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Let <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to provide <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> remote access to access to applications installed on this device when connected."</string> + <string name="permission_apps" msgid="6142133265286656158">"Apps"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Stream your phone’s apps"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access this information from your phone"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to access your phone’s photos, media, and notifications"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access this information from your phone"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Notifications"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Can read all notifications, including information like contacts, messages, and photos"</string> + <string name="permission_storage" msgid="6831099350839392343">"Photos and media"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play services"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to stream apps between your devices"</string> <string name="profile_name_generic" msgid="6851028682723034988">"device"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Allow"</string> <string name="consent_no" msgid="2640796915611404382">"Don’t allow"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transfer app permissions to your watch"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"To make it easier to set up your watch, apps installed on your watch during setup will use the same permissions as your phone.\n\n These permissions may include access to your watch’s microphone and location."</string> + <string name="consent_back" msgid="2560683030046918882">"Back"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Give apps on <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> the same permissions as on <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>This may include Microphone, Camera, and Location access, and other sensitive permissions on <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>You can change these permissions any time in your Settings on <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml index 5423d3eeff87..d5c0c06000f6 100644 --- a/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml +++ b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Elige un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para que <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> lo administre"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> podrá interactuar con tus notificaciones y acceder a los permisos de Teléfono, SMS, Contactos y Calendario."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> podrá interactuar con tus notificaciones y acceder a los permisos de Teléfono, SMS, Contactos y Calendario."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"¿Deseas permitir que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> transmita aplicaciones?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Permite que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> proporcione a <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> acceso remoto a las aplicaciones instaladas en este teléfono cuando esté conectado."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Permite que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> proporcione <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> acceso remoto a las aplicaciones instaladas en esta tablet cuando esté conectada."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Permite que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> proporcione a <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> acceso remoto a las aplicaciones instaladas en este dispositivo cuando esté conectado."</string> + <string name="permission_apps" msgid="6142133265286656158">"Apps"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Transmitir las apps de tu teléfono"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Permite que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acceda a esta información de tu teléfono"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Servicios multidispositivo"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> solicita tu permiso en nombre de <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para acceder a las fotos, el contenido multimedia y las notificaciones de tu teléfono"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Permite que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acceda a esta información de tu teléfono"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Notificaciones"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Puede leer todas las notificaciones, incluso con información como contactos, mensajes y fotos"</string> + <string name="permission_storage" msgid="6831099350839392343">"Fotos y contenido multimedia"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Servicios de Google Play"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> solicita tu permiso en nombre de <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para transmitir apps entre dispositivos"</string> <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Permitir"</string> <string name="consent_no" msgid="2640796915611404382">"No permitir"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transfiere los permisos de la app a tu reloj"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Para que sea más fácil configurar tu reloj, las apps que se instalen en este durante la configuración usarán los mismos permisos que tu teléfono.\n\n Es posible que estos permisos incluyan el acceso al micrófono y a la ubicación del reloj."</string> + <string name="consent_back" msgid="2560683030046918882">"Atrás"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"¿Quieres otorgar a las apps de <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> los mismos permisos que tienen en <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Esto puede incluir el acceso al micrófono, la cámara y la ubicación, así como otros permisos sensibles del dispositivo <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Puedes cambiar estos permisos en cualquier momento en la Configuración del dispositivo <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-es/strings.xml b/packages/CompanionDeviceManager/res/values-es/strings.xml index ccbdd250dad2..aabf7f6ccaff 100644 --- a/packages/CompanionDeviceManager/res/values-es/strings.xml +++ b/packages/CompanionDeviceManager/res/values-es/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Elige un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para gestionarlo con <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> podrá interactuar con tus notificaciones y acceder a tus permisos de teléfono, SMS, contactos y calendario."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> podrá interactuar con tus notificaciones y acceder a tus permisos de teléfono, SMS, contactos y calendario."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"¿Permitir que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> inicie aplicaciones?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Permite que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acceda de forma remota a las aplicaciones instaladas en este teléfono cuando <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> esté conectado a Internet."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Permite que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acceda de forma remota a las aplicaciones instaladas en este tablet cuando <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> esté conectado a Internet."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Permite que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acceda de forma remota a las aplicaciones instaladas en este dispositivo cuando <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> esté conectado a Internet."</string> + <string name="permission_apps" msgid="6142133265286656158">"Aplicaciones"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Emite las aplicaciones de tu teléfono"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Permitir que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acceda a esta información desde tu teléfono"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Servicios multidispositivo"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> está pidiendo permiso en nombre de tu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para acceder a las fotos, los archivos multimedia y las notificaciones de tu teléfono"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Permitir que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acceda a esta información desde tu teléfono"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Notificaciones"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Puede leer todas las notificaciones, incluida información como contactos, mensajes y fotos"</string> + <string name="permission_storage" msgid="6831099350839392343">"Fotos y elementos multimedia"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Servicios de Google Play"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> está pidiendo permiso en nombre de tu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para emitir aplicaciones en otros dispositivos tuyos"</string> <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Permitir"</string> <string name="consent_no" msgid="2640796915611404382">"No permitir"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transferir permisos de aplicaciones a tu reloj"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Para configurar fácilmente tu reloj, las aplicaciones que instales en él durante la configuración usarán los mismos permisos que tengan en tu teléfono.\n\n Estos permisos pueden incluir acceso al micrófono y a la ubicación del reloj."</string> + <string name="consent_back" msgid="2560683030046918882">"Atrás"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"¿Dar a las aplicaciones de <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> los mismos permisos que tienen en <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Esto puede incluir acceso al micrófono, la cámara y la ubicación, así como otros permisos sensibles de <p><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Puedes cambiar estos permisos cuando quieras en los ajustes de <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>."</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-et/strings.xml b/packages/CompanionDeviceManager/res/values-et/strings.xml index d8f1e9920736..57f1b1f3cf76 100644 --- a/packages/CompanionDeviceManager/res/values-et/strings.xml +++ b/packages/CompanionDeviceManager/res/values-et/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Valige seade <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, mida haldab rakendus <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> saab kasutada teie märguandeid ning pääseda juurde teie telefoni, SMS-ide, kontaktide ja kalendri lubadele."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> saab kasutada teie märguandeid ning pääseda juurde teie telefoni, SMS-ide, kontaktide ja kalendri lubadele."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Kas lubada rakendusel <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> rakendusi voogesituse kaudu üle kanda?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Rakendusel <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> lubatakse seadmele <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> pakkuda kaugjuurdepääsu, et ühendatuna pääseda juurde sellesse telefoni installitud rakendustele."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Rakendusel <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> lubatakse seadmele <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> pakkuda kaugjuurdepääsu, et ühendatuna pääseda juurde sellesse tahvelarvutisse installitud rakendustele."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Rakendusel <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> lubatakse seadmele <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> pakkuda kaugjuurdepääsu, et ühendatuna pääseda juurde sellesse seadmesse installitud rakendustele."</string> + <string name="permission_apps" msgid="6142133265286656158">"Rakendused"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Telefoni rakenduste voogesitamine"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Lubage rakendusel <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pääseda teie telefonis juurde sellele teabele"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Seadmeülesed teenused"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> taotleb teie seadme <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> nimel luba pääseda juurde telefoni fotodele, meediale ja märguannetele"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Lubage rakendusel <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pääseda teie telefonis juurde sellele teabele"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Märguanded"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Kõikide märguannete, sealhulgas teabe, nagu kontaktid, sõnumid ja fotod, lugemine"</string> + <string name="permission_storage" msgid="6831099350839392343">"Fotod ja meedia"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play teenused"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> taotleb teie seadme <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> nimel luba teie seadmete vahel rakendusi voogesitada"</string> <string name="profile_name_generic" msgid="6851028682723034988">"seade"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Luba"</string> <string name="consent_no" msgid="2640796915611404382">"Ära luba"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Rakenduste lubade kellale ülekandmine"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Selleks et muuta kella seadistamine lihtsamaks, kasutavad teie kellas seadistamise ajal installitud rakendused samasid lubasid, mis neile telefonis antud on.\n\n Need load võivad hõlmata juurdepääsuluba kella mikrofonile ja asukohale."</string> + <string name="consent_back" msgid="2560683030046918882">"Tagasi"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Kas anda rakendustele seadmes <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> samad load, mis seadmes <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>See võib hõlmata mikrofoni, kaamerat ja juurdepääsu asukohale ning muid tundlikke lube seadmes <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Võite neid lube seadme <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> seadetes igal ajal muuta.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-eu/strings.xml b/packages/CompanionDeviceManager/res/values-eu/strings.xml index de768249916c..24b89548a94b 100644 --- a/packages/CompanionDeviceManager/res/values-eu/strings.xml +++ b/packages/CompanionDeviceManager/res/values-eu/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Aukeratu <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> aplikazioak kudeatu beharreko <xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"Jakinarazpenekin interakzioan aritzeko eta telefonoa, SMSak, kontaktuak eta egutegia erabiltzeko baimenak izango ditu <xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioak."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"Jakinarazpenekin interakzioan aritzeko eta telefonoa, SMSak, kontaktuak eta egutegia erabiltzeko baimenak izango ditu <xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioak."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Aplikazioak igortzeko baimena eman nahi diozu <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> aplikazioari?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Utzi <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> aplikazioari <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> urrunetik atzitzen, telefonoa konektatuta dagoenean bertan instalatuta dauden aplikazioetarako sarbidea izateko."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Utzi <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> aplikazioari <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> urrunetik atzitzen, tableta konektatuta dagoenean bertan instalatuta dauden aplikazioetarako sarbidea izateko."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Utzi <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> aplikazioari <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> urrunetik atzitzen, gailua konektatuta dagoenean bertan instalatuta dauden aplikazioetarako sarbidea izateko."</string> + <string name="permission_apps" msgid="6142133265286656158">"Aplikazioak"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Igorri zuzenean telefonoko aplikazioak"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Eman informazioa telefonotik hartzeko baimena <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> aplikazioari"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Gailu bat baino gehiagotarako zerbitzuak"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"Telefonoko argazkiak, multimedia-edukia eta jakinarazpenak atzitzeko baimena eskatzen ari da <xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> gailuaren izenean"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Eman informazio hori telefonotik hartzeko baimena <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> aplikazioari"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Jakinarazpenak"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Jakinarazpen guztiak irakur ditzake; besteak beste, kontaktuak, mezuak, argazkiak eta antzeko informazioa"</string> + <string name="permission_storage" msgid="6831099350839392343">"Argazkiak eta multimedia-edukia"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play Services"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"Gailu batetik bestera aplikazioak igortzeko baimena eskatzen ari da <xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> gailuaren izenean"</string> <string name="profile_name_generic" msgid="6851028682723034988">"gailua"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Eman baimena"</string> <string name="consent_no" msgid="2640796915611404382">"Ez eman baimenik"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transferitu aplikazio-baimenak erlojura"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Erlojua errazago konfiguratzeko, konfigurazio-prozesua abian zen bitartean erlojuan instalatutako aplikazioek telefonoak darabiltzan baimen berak erabiliko dituzte.\n\n Baliteke baimen horien artean erlojuaren mikrofonoa eta kokapena atzitzeko baimenak egotea."</string> + <string name="consent_back" msgid="2560683030046918882">"Atzera"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> gailuan dituzten baimen berberak eman nahi dizkiezu <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> gailuko aplikazioei?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Haien artean, baliteke <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> gailuaren mikrofonoa, kamera, kokapenerako sarbidea eta beste kontuzko baimen batzuk egotea.</p> <p>Baimen horiek edonoiz alda ditzakezu <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> gailuaren ezarpenetan.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-fa/strings.xml b/packages/CompanionDeviceManager/res/values-fa/strings.xml index 65ed2dde864f..ba96c2ce7278 100644 --- a/packages/CompanionDeviceManager/res/values-fa/strings.xml +++ b/packages/CompanionDeviceManager/res/values-fa/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"انتخاب <xliff:g id="PROFILE_NAME">%1$s</xliff:g> برای مدیریت کردن با <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> میتواند با اعلانهای شما تعامل داشته باشد و به اجازههای «تلفن»، «پیامک»، «مخاطبین»، و «تقویم» دسترسی پیدا کند."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> میتواند با اعلانهای شما تعامل داشته باشد و به اجازههای «تلفن»، «پیامک»، «مخاطبین»، و «تقویم» دسترسی پیدا کند."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"به <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> اجازه میدهید برنامهها را جاریسازی کند؟"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"به <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> اجازه میدهد برای <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> دسترسی ازراهدور ارائه دهد تا دستگاه موردنظر بتواند هنگام اتصال، به برنامههای نصبشده در این تلفن دسترسی داشته باشد."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"به <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> اجازه میدهد برای <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> دسترسی ازراهدور ارائه دهد تا دستگاه موردنظر بتواند هنگام اتصال، به برنامههای نصبشده در این رایانه لوحی دسترسی داشته باشد."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"به <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> اجازه میدهد برای <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> دسترسی ازراهدور ارائه دهد تا دستگاه موردنظر بتواند هنگام اتصال، به برنامههای نصبشده در این دستگاه دسترسی داشته باشد."</string> + <string name="permission_apps" msgid="6142133265286656158">"برنامهها"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"جاریسازی برنامههای تلفن"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"اجازه دادن به <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> برای دسترسی به اطلاعات تلفن"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"سرویسهای بیندستگاهی"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> اجازه میخواهد ازطرف <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> به عکسها، رسانه، و اعلانهای تلفن شما دسترسی پیدا کند"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> مجاز میشود به این اطلاعات در دستگاهتان دسترسی پیدا کند"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"اعلانها"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"میتواند همه اعلانها، ازجمله اطلاعاتی مثل مخاطبین، پیامها، و عکسها را بخواند"</string> + <string name="permission_storage" msgid="6831099350839392343">"عکسها و رسانهها"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"خدمات Google Play"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> اجازه میخواهد ازطرف <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> برنامهها را بین دستگاههای شما جاریسازی کند"</string> <string name="profile_name_generic" msgid="6851028682723034988">"دستگاه"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"مجاز است"</string> <string name="consent_no" msgid="2640796915611404382">"مجاز نبودن"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"انتقال اجازههای برنامه به ساعت"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"برای آسانتر کردن راهاندازی ساعت، برنامههای نصبشده در ساعت درحین راهاندازی از همان اجازههای تلفن استفاده خواهند کرد.\n\n ممکن است این اجازهها شامل دسترسی به میکروفون و مکان ساعت باشد."</string> + <string name="consent_back" msgid="2560683030046918882">"برگشت"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"به برنامههای موجود در <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> همان اجازههای <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> داده شود؟"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>این اجازهها میتواند شامل دسترسی به «میکروفون»، «دوربین»، و «مکان»، و دیگر اجازههای حساس در <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> شود.</p> <p>هروقت بخواهید میتوانید این اجازهها را در «تنظیمات» در <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> تغییر دهید.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-fi/strings.xml b/packages/CompanionDeviceManager/res/values-fi/strings.xml index c8dbeb54402a..50962f5b1348 100644 --- a/packages/CompanionDeviceManager/res/values-fi/strings.xml +++ b/packages/CompanionDeviceManager/res/values-fi/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Valitse <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, jota <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> hallinnoi"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> saa luvan hallinnoida ilmoituksiasi sekä pääsyn puhelimeesi, tekstiviesteihisi, kontakteihisi ja kalenteriisi."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> saa luvan hallinnoida ilmoituksiasi sekä pääsyn puhelimeesi, tekstiviesteihisi, kontakteihisi ja kalenteriisi."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Saako <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> striimata sovelluksia?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Salli, että <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> voi saada sovellukselta (<strong><xliff:g id="APP_NAME">%1$s</xliff:g>) etäpääsyoikeuden tälle puhelimelle asennettuihin sovelluksiin, kun laitteet on yhdistetty."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Salli, että <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> voi saada sovellukselta (<strong><xliff:g id="APP_NAME">%1$s</xliff:g>) etäpääsyoikeuden tälle tabletille asennettuihin sovelluksiin, kun laitteet on yhdistetty."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Salli, että <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> voi saada sovellukselta (<strong><xliff:g id="APP_NAME">%1$s</xliff:g>) etäpääsyoikeuden tälle laitteelle asennettuihin sovelluksiin, kun laitteet on yhdistetty."</string> + <string name="permission_apps" msgid="6142133265286656158">"Sovellukset"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Striimaa puhelimen sovelluksia"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Salli, että <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> saa pääsyn näihin puhelimesi tietoihin"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Laitteidenväliset palvelut"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> pyytää laitteeltasi (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) lupaa päästä puhelimesi kuviin, mediaan ja ilmoituksiin"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Salli pääsy tähän tietoon puhelimellasi: <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Ilmoitukset"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Voi lukea kaikkia ilmoituksia, esim. kontakteihin, viesteihin ja kuviin liittyviä tietoja"</string> + <string name="permission_storage" msgid="6831099350839392343">"Kuvat ja media"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play Palvelut"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> pyytää laitteeltasi (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) lupaa striimata sovelluksia laitteidesi välillä"</string> <string name="profile_name_generic" msgid="6851028682723034988">"laite"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Salli"</string> <string name="consent_no" msgid="2640796915611404382">"Älä salli"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Siirrä sovellusluvat kelloon"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Sovellukset, jotka on asennettu kelloon käyttöönoton aikana, käyttävät samoja lupia kuin puhelin. Näin kello on helpompi ottaa käyttöön.\n\n Näihin lupiin saattaa kuulua pääsy kellon mikrofoniin ja sijaintiin."</string> + <string name="consent_back" msgid="2560683030046918882">"Takaisin"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Anna laitteen <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> sovelluksille samat luvat kuin laitteella <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Tähän voi kuulua pääsy mikrofoniin, kameraan ja sijaintiin sekä muita arkaluontoisia lupia laitteella <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Voit muuttaa lupia asetuksista milloin tahansa laitteella <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml b/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml index 3d5898b0a5a9..4d784531fd02 100644 --- a/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml +++ b/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Choisissez un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> qui sera géré par <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> aura l\'autorisation d\'interagir avec vos notifications et d\'accéder aux autorisations pour votre téléphone, vos messages texte, vos contacts et votre agenda."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> aura l\'autorisation d\'interagir avec vos notifications et d\'accéder aux autorisations pour votre téléphone, vos messages texte, vos contacts et votre agenda."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Permettre à l\'application <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> de diffuser des applications?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Permettez à l\'application <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> de donner à l\'appareil <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> un accès à distance aux applications installées sur ce téléphone lorsqu\'il est connecté."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Permettez à l\'application <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> de donner à l\'appareil <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> un accès à distance aux applications installées sur cette tablette lorsqu\'elle est connectée."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Permettez à l\'application <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> de donner à l\'appareil <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> un accès à distance aux applications installées sur cet appareil lorsqu\'il est connecté."</string> + <string name="permission_apps" msgid="6142133265286656158">"Applications"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Diffusez les applications de votre téléphone"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Autorisez <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> à accéder à ces informations à partir de votre téléphone"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Services multiappareils"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> demande l\'autorisation au nom de votre <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> pour accéder aux photos, aux fichiers multimédias et aux notifications de votre téléphone"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Autorisez <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> à accéder à ces informations à partir de votre téléphone"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Notifications"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Peut lire toutes les notifications, y compris les renseignements tels que les contacts, les messages et les photos"</string> + <string name="permission_storage" msgid="6831099350839392343">"Photos et fichiers multimédias"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Services Google Play"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> demande l\'autorisation au nom de votre <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> pour diffuser des applications entre vos appareils"</string> <string name="profile_name_generic" msgid="6851028682723034988">"appareil"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Autoriser"</string> <string name="consent_no" msgid="2640796915611404382">"Ne pas autoriser"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transférer les autorisations de l\'application à votre montre"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Pour faciliter la configuration de votre montre, les applications installées sur celle-ci reprennent les mêmes autorisations que celles installées sur votre téléphone.\n\n Ces autorisations peuvent comprendre l\'accès au microphone et à la position de votre montre."</string> + <string name="consent_back" msgid="2560683030046918882">"Retour"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Accorder aux applications sur <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> les autorisations déjà accordées sur <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Cela peut comprendre l\'accès au microphone, à l\'appareil photo et à la position, ainsi que d\'autres autorisations sensibles sur <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Vous pouvez modifier ces autorisations en tout temps dans vos paramètres sur <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-fr/strings.xml b/packages/CompanionDeviceManager/res/values-fr/strings.xml index ecd89aa97ec9..b3fd930d616d 100644 --- a/packages/CompanionDeviceManager/res/values-fr/strings.xml +++ b/packages/CompanionDeviceManager/res/values-fr/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Sélectionner le/la <xliff:g id="PROFILE_NAME">%1$s</xliff:g> qui sera géré(e) par <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> aura l\'autorisation d\'interagir avec vos notifications et d\'accéder au téléphone, aux SMS, aux contacts et à l\'agenda."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> aura l\'autorisation d\'interagir avec vos notifications et d\'accéder au téléphone, aux SMS, aux contacts et à l\'agenda."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Autoriser <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> à diffuser des applis en streaming ?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Autoriser <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> à accéder à distance aux applis installées sur <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> quand ce téléphone est connecté à Internet."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Autoriser <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> à accéder à distance aux applis installées sur <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> quand cette tablette est connectée à Internet."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Autoriser <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> à accéder à distance aux applis installées sur <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> quand cet appareil est connecté à Internet."</string> + <string name="permission_apps" msgid="6142133265286656158">"Applis"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Caster les applis de votre téléphone"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Autoriser <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> à accéder à ces informations depuis votre téléphone"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Services inter-appareils"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> demande l\'autorisation au nom de votre <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> pour accéder aux photos, contenus multimédias et notifications de votre téléphone"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Autoriser <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> à accéder à ces informations depuis votre téléphone"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Notifications"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Peut lire toutes les notifications, y compris des informations comme les contacts, messages et photos"</string> + <string name="permission_storage" msgid="6831099350839392343">"Photos et contenus multimédias"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Services Google Play"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> demande l\'autorisation au nom de votre <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> pour caster des applis d\'un appareil à l\'autre"</string> <string name="profile_name_generic" msgid="6851028682723034988">"appareil"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Autoriser"</string> <string name="consent_no" msgid="2640796915611404382">"Ne pas autoriser"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transférer les autorisations de l\'appli vers la montre"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Pour que votre montre soit plus facile à configurer, les applis qui y sont installées pendant la configuration utiliseront les mêmes autorisations que votre téléphone.\n\n Il peut s\'agir, par exemple, de l\'accès au micro et à la position de votre montre."</string> + <string name="consent_back" msgid="2560683030046918882">"Retour"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Accorder les mêmes autorisations aux applis sur <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> que sur <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> ?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Il peut s\'agir de l\'accès au micro, à l\'appareil photo et à la position, et d\'autres autorisations sensibles sur l\'appareil <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Vous pouvez modifier ces autorisations à tout moment dans les paramètres de l\'appareil <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-gl/strings.xml b/packages/CompanionDeviceManager/res/values-gl/strings.xml index d060f29a7e02..abfec8603839 100644 --- a/packages/CompanionDeviceManager/res/values-gl/strings.xml +++ b/packages/CompanionDeviceManager/res/values-gl/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Escolle un perfil (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>) para que o xestione a aplicación <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> poderá interactuar coas túas notificacións e acceder aos permisos do teu teléfono, das mensaxes, dos contactos e do calendario."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> poderá interactuar coas túas notificacións e acceder aos permisos do teu teléfono, das mensaxes, dos contactos e do calendario."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Queres permitir que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> emita aplicacións noutros dispositivos?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Permite que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> lle outorgue a <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> acceso remoto a aplicacións instaladas neste teléfono cando teña conexión a Internet."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Permite que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> lle outorgue a <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> acceso remoto a aplicacións instaladas nesta tableta cando teña conexión a Internet."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Permite que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> lle outorgue a <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> acceso remoto a aplicacións instaladas neste dispositivo cando teña conexión a Internet."</string> + <string name="permission_apps" msgid="6142133265286656158">"Aplicacións"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Emite as aplicacións do teu teléfono"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Permitir que a aplicación <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acceda a esta información desde o teu teléfono"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Servizos multidispositivo"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> está solicitando permiso en nome do teu dispositivo (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) para acceder ás fotos, ao contido multimedia e ás notificacións do teléfono"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Permitir que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acceda a esta información desde o teu teléfono"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Notificacións"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Pode ler todas as notificacións (que poden incluír información como contactos, mensaxes e fotos)"</string> + <string name="permission_storage" msgid="6831099350839392343">"Fotos e contido multimedia"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Servizos de Google Play"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> está solicitando permiso en nome do teu dispositivo (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) para emitir aplicacións entre os teus aparellos"</string> <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Permitir"</string> <string name="consent_no" msgid="2640796915611404382">"Non permitir"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transferir os permisos de aplicacións ao reloxo"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Para que che resulte máis doado configurar o reloxo, as aplicacións que instales nel durante a configuración usarán os mesmos permisos que o teléfono.\n\n Entre estes permisos poden estar incluídos os de acceso ao micrófono e á localización do teléfono."</string> + <string name="consent_back" msgid="2560683030046918882">"Atrás"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Queres darlles ás aplicacións de <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> os mesmos permisos que teñen as de <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Con esta acción podes conceder acceso ao micrófono, á cámara e á localización, así como outros permisos de acceso á información confidencial de <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Podes cambiar estes permisos en calquera momento na configuración de <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-gu/strings.xml b/packages/CompanionDeviceManager/res/values-gu/strings.xml index d06d8c677fd4..881415e0ea41 100644 --- a/packages/CompanionDeviceManager/res/values-gu/strings.xml +++ b/packages/CompanionDeviceManager/res/values-gu/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> દ્વારા મેનેજ કરવા માટે કોઈ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> પસંદ કરો"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g>ને તમારા નોટિફિકેશન સાથે ક્રિયાપ્રતિક્રિયા કરવાની તેમજ તમારો ફોન, SMS, સંપર્કો તેમજ કૅલેન્ડરની પરવાનગીઓ ઍક્સેસ કરવાની મંજૂરી આપવામાં આવશે."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g>ને તમારા નોટિફિકેશન સાથે ક્રિયાપ્રતિક્રિયા કરવાની તેમજ તમારો ફોન, SMS, સંપર્કો તેમજ કૅલેન્ડરની પરવાનગીઓ ઍક્સેસ કરવાની મંજૂરી આપવામાં આવશે."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"શું </strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ને ઍપ્લિકેશનો સ્ટ્રીમ કરવાની મંજૂરી આપીએ?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"જ્યારે કનેક્ટ કરવામાં આવે, ત્યારે આ ફોન પર ઇન્સ્ટૉલ કરવામાં આવેલી ઍપ્લિકેશનોનો રિમોટ ઍક્સેસ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ને <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>ને પ્રદાન કરવા દો."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"જ્યારે કનેક્ટ કરવામાં આવે, ત્યારે આ ટૅબ્લેટ પર ઇન્સ્ટૉલ કરવામાં આવેલી ઍપ્લિકેશનોનો રિમોટ ઍક્સેસ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ને <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>ને પ્રદાન કરવા દો."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"જ્યારે કનેક્ટ કરવામાં આવે, ત્યારે આ ડિવાઇસ પર ઇન્સ્ટૉલ કરવામાં આવેલી ઍપ્લિકેશનોનો રિમોટ ઍક્સેસ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ને <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>ને પ્રદાન કરવા દો."</string> + <string name="permission_apps" msgid="6142133265286656158">"ઍપ"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"તમારા ફોનની ઍપ સ્ટ્રીમ કરો"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"તમારા ફોનમાંથી આ માહિતી ઍક્સેસ કરવા માટે, <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ને મંજૂરી આપો"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"ક્રોસ-ડિવાઇસ સેવાઓ"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> તમારા <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> વતી તમારા ફોનના ફોટા, મીડિયા અને નોટિફિકેશન ઍક્સેસ કરવાની પરવાનગીની વિનંતી કરી રહી છે"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"તમારા ફોનમાંથી આ માહિતી ઍક્સેસ કરવા માટે, <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ને મંજૂરી આપો"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"નોટિફિકેશન"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"સંપર્કો, મેસેજ અને ફોટા જેવી માહિતી સહિતના બધા નોટિફિકેશન વાંચી શકે છે"</string> + <string name="permission_storage" msgid="6831099350839392343">"ફોટા અને મીડિયા"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play સેવાઓ"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> તમારા <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> વતી તમારા ડિવાઇસ વચ્ચે ઍપ સ્ટ્રીમ કરવાની પરવાનગીની વિનંતી કરી રહી છે"</string> <string name="profile_name_generic" msgid="6851028682723034988">"ડિવાઇસ"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"મંજૂરી આપો"</string> <string name="consent_no" msgid="2640796915611404382">"મંજૂરી આપશો નહીં"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"તમારી ઘડિયાળમાં ઍપ પરવાનગીઓ ટ્રાન્સફર કરો"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"તમારી ઘડિયાળનું સેટઅપ કરવાનું સરળ બનાવવા માટે, સેટઅપ દરમિયાન તમારી ઘડિયાળ પર ઇન્સ્ટૉલ કરેલી ઍપ દ્વારા તમારા ફોન પર મળેલી પરવાનગીઓનો ઉપયોગ કરવામાં આવશે.\n\n આ પરવાનગીઓમાં તમારી ઘડિયાળના માઇક્રોફોન અને સ્થાન સંબંધિત માહિતીનો ઍક્સેસ શામેલ હોઈ શકે છે."</string> + <string name="consent_back" msgid="2560683030046918882">"પાછળ"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> પરની ઍપને <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> પર છે તે જ પરવાનગીઓ આપીએ?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>આમાં <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> પરના માઇક્રોફોન, કૅમેરા અને સ્થાનના ઍક્સેસ તથા અન્ય સંવેદનશીલ માહિતીની પરવાનગીઓ શામેલ હોઈ શકે છે.</p> <p>તમે <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> પર તમારા સેટિંગમાં તમે કોઈપણ સમયે આ પરવાનગીઓને બદલી શકો છો.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-hi/strings.xml b/packages/CompanionDeviceManager/res/values-hi/strings.xml index 1be6af8af0ec..84c8a8ee6808 100644 --- a/packages/CompanionDeviceManager/res/values-hi/strings.xml +++ b/packages/CompanionDeviceManager/res/values-hi/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"कोई <xliff:g id="PROFILE_NAME">%1$s</xliff:g> चुनें, ताकि उसे <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> की मदद से प्रबंधित किया जा सके"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> आपकी सूचनाओं पर कार्रवाई कर पाएगा. साथ ही, यह आपके फ़ोन, एसएमएस, संपर्कों, और कैलेंडर की अनुमतियों को भी ऐक्सेस कर पाएगा."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> आपकी सूचनाओं पर कार्रवाई कर पाएगा. साथ ही, यह आपके फ़ोन, एसएमएस, संपर्कों, और कैलेंडर की अनुमतियों को भी ऐक्सेस कर पाएगा."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> को ऐप्लिकेशन स्ट्रीम करने की अनुमति देनी है?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"कनेक्ट होने पर, <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> को <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> के रिमोट ऐक्सेस की अनुमति दें, ताकि इस फ़ोन पर इंस्टॉल किए गए ऐप्लिकेशन ऐक्सेस किए जा सकें."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"कनेक्ट होने पर, <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> को <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> के रिमोट ऐक्सेस की अनुमति दें, ताकि इस टैबलेट पर इंस्टॉल किए गए ऐप्लिकेशन ऐक्सेस किए जा सकें."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"कनेक्ट होने पर, <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> को <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> के रिमोट ऐक्सेस की अनुमति दें, ताकि इस डिवाइस पर इंस्टॉल किए गए ऐप्लिकेशन ऐक्सेस किए जा सकें."</string> + <string name="permission_apps" msgid="6142133265286656158">"ऐप्लिकेशन"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"अपने फ़ोन के ऐप्लिकेशन को स्ट्रीम करें"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> को अपने फ़ोन से यह जानकारी ऐक्सेस करने की अनुमति दें"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"क्रॉस-डिवाइस से जुड़ी सेवाएं"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> आपके <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> की ओर से, फ़ोन में मौजूद फ़ोटो, मीडिया, और सूचनाओं को ऐक्सेस करने की अनुमति मांग रहा है"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> को अपने फ़ोन से यह जानकारी ऐक्सेस करने की अनुमति दें"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"सूचनाएं"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"इससे सभी सूचनाएं देखी जा सकती हैं. इसमें संपर्क, मैसेज, और फ़ोटो जैसी जानकारी शामिल होती है"</string> + <string name="permission_storage" msgid="6831099350839392343">"फ़ोटो और मीडिया"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play सेवाएं"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> आपके <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> की ओर से, डिवाइसों के बीच ऐप्लिकेशन को स्ट्रीम करने की अनुमति मांग रहा है"</string> <string name="profile_name_generic" msgid="6851028682723034988">"डिवाइस"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"अनुमति दें"</string> <string name="consent_no" msgid="2640796915611404382">"अनुमति न दें"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"ऐप्लिकेशन से जुड़ी अनुमतियों को अपनी वॉच में ट्रांसफ़र करें"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"वॉच को सेट अप करने की प्रोसेस को आसान बनाने के लिए, उस पर इंस्टॉल किए गए ऐप्लिकेशन को भी वही अनुमतियां मिलेंगी जो आपने उन ऐप्लिकेशन को फ़ोन पर दी होंगी.\n\n इन अनुमतियों में, आपकी वॉच के माइक्रोफ़ोन और जगह की जानकारी का ऐक्सेस शामिल हो सकता है."</string> + <string name="consent_back" msgid="2560683030046918882">"वापस जाएं"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"क्या <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> पर ऐप्लिकेशन को वही अनुमतियां देनी हैं जो <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> पर दी हैं?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>इसमें <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> पर मौजूद माइक्रोफ़ोन, कैमरा, जगह की जानकारी को ऐक्सेस करने, और अन्य संवेदनशील जानकारी ऐक्सेस करने की अनुमतियां शामिल हो सकती हैं.</p> <p>किसी भी समय <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> की सेटिंग में जाकर, इन अनुमतियों में बदलाव किए जा सकते हैं.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-hr/strings.xml b/packages/CompanionDeviceManager/res/values-hr/strings.xml index 610b7bdffa70..fda9cfaf5dcf 100644 --- a/packages/CompanionDeviceManager/res/values-hr/strings.xml +++ b/packages/CompanionDeviceManager/res/values-hr/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Odaberite profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kojim će upravljati aplikacija <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> moći će stupati u interakciju s vašim obavijestima i pristupati dopuštenjima za telefon, SMS-ove, kontakte i kalendar."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> moći će stupati u interakciju s vašim obavijestima i pristupati dopuštenjima za telefon, SMS-ove, kontakte i kalendar."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Dopustiti aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pokretanje streama aplikacija?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Dopustite aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da telefonu <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> omogući udaljeni pristup aplikacijama koje su instalirane na tom telefonu kada su povezani."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Dopustite aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da tabletu <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> omogući udaljeni pristup aplikacijama koje su instalirane na tom tabletu kada su povezani."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Dopustite aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da uređaju <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> omogući udaljeni pristup aplikacijama koje su instalirane na tom uređaju kada su povezani."</string> + <string name="permission_apps" msgid="6142133265286656158">"Aplikacije"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Streaming aplikacija vašeg telefona"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Omogućite aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da pristupa informacijama s vašeg telefona"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Usluge na različitim uređajima"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> zahtijeva dopuštenje u ime vašeg uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> da pristupi fotografijama, medijskim sadržajima i obavijestima na telefonu"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Omogućite aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da pristupa informacijama s vašeg telefona"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Obavijesti"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Može čitati sve obavijesti, uključujući informacije kao što su kontakti, poruke i fotografije"</string> + <string name="permission_storage" msgid="6831099350839392343">"Fotografije i mediji"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Usluge za Google Play"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> zahtijeva dopuštenje u ime vašeg uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> za streamanje aplikacija između vaših uređaja"</string> <string name="profile_name_generic" msgid="6851028682723034988">"uređaj"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Dopusti"</string> <string name="consent_no" msgid="2640796915611404382">"Nemoj dopustiti"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Prijenos dopuštenja aplikacije na sat"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Kako bi postavljanje sata bilo jednostavnije, aplikacije instalirane na satu će tijekom postavljanja upotrebljavati ista dopuštenja kao telefon.\n\n Ta dopuštenja mogu uključivati pristup mikrofonu i lokaciji sata."</string> + <string name="consent_back" msgid="2560683030046918882">"Natrag"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Davanje jednakih dopuštenja aplikacijama na uređaju <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> kao i na uređaju <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>To može uključivati pristup mikrofonu, kameri i lokaciji i druga dopuštenja za osjetljive podatke na uređaju <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Ta dopuštenja uvijek možete promijeniti u postavkama na uređaju <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-hu/strings.xml b/packages/CompanionDeviceManager/res/values-hu/strings.xml index 625a3e9cd4aa..a65b312e3d71 100644 --- a/packages/CompanionDeviceManager/res/values-hu/strings.xml +++ b/packages/CompanionDeviceManager/res/values-hu/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"A(z) <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> alkalmazással kezelni kívánt <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kiválasztása"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> műveleteket végezhet majd az értesítésekkel, és hozzáférhet a telefonra, az SMS-ekre, a névjegyekre és a naptárra vonatkozó engedélyekhez."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> műveleteket végezhet majd az értesítésekkel, és hozzáférhet a telefonra, az SMS-ekre, a névjegyekre és a naptárra vonatkozó engedélyekhez."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Engedélyezi a(z) <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> alkalmazásnak appok streamelését?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Engedélyezheti a(z) <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> alkalmazásnak, hogy a(z) <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> eszköz számára távoli hozzáférést biztosítson a telefonra telepített alkalmazásokhoz, amikor a telefon csatlakoztatva van."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Engedélyezheti a(z) <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> alkalmazásnak, hogy a(z) <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> eszköz számára távoli hozzáférést biztosítson a táblagépre telepített alkalmazásokhoz, amikor a táblagép csatlakoztatva van."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Engedélyezheti a(z) <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> alkalmazásnak, hogy a(z) <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> eszköz számára távoli hozzáférést biztosítson az eszközre telepített alkalmazásokhoz, amikor az eszköz csatlakoztatva van."</string> + <string name="permission_apps" msgid="6142133265286656158">"Alkalmazások"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"A telefon alkalmazásainak streamelése"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Engedélyezi a(z) „<xliff:g id="APP_NAME">%1$s</xliff:g>” alkalmazás számára az információhoz való hozzáférést a telefonról"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Többeszközös szolgáltatások"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> engedélyt kér a(z) <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> nevében a telefonon tárolt fotókhoz, médiatartalmakhoz és értesítésekhez való hozzáféréshez"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Engedélyezi a(z) „<xliff:g id="APP_NAME">%1$s</xliff:g>” alkalmazás számára az információhoz való hozzáférést a telefonról"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Értesítések"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Elolvashat minden értesítést, ideértve az olyan információkat, mint a névjegyek, az üzenetek és a fotók"</string> + <string name="permission_storage" msgid="6831099350839392343">"Fotók és médiatartalmak"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play-szolgáltatások"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> engedélyt kér a(z) <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> nevében az alkalmazások eszközök közötti streameléséhez"</string> <string name="profile_name_generic" msgid="6851028682723034988">"eszköz"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Engedélyezés"</string> <string name="consent_no" msgid="2640796915611404382">"Tiltás"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Alkalmazásengedélyek átvitele az órára"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Az óra beállításának megkönnyítése érdekében a beállítás során az órára telepített alkalmazások ugyanazokat az engedélyeket használják majd, mint a telefonja.\n\n Ezek az engedélyek magukban foglalhatják az óra mikrofonjához és helyadataihoz való hozzáférést."</string> + <string name="consent_back" msgid="2560683030046918882">"Vissza"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Ugyanolyan engedélyeket ad a(z) <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> eszközön található alkalmazásoknak, mint a(z) <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> eszköz esetén?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Ide tartozhatnak a mikrofonhoz, a kamerához és a helyhez való hozzáférések, valamint a(z) <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> eszközön érvényes egyéb, bizalmas adatokra vonatkozó hozzáférési engedélyek is.</p> <p>Ezeket az engedélyeket bármikor módosíthatja a(z) <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> eszköz beállításai között.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-hy/strings.xml b/packages/CompanionDeviceManager/res/values-hy/strings.xml index f09441fcdb4c..f07a785a46a9 100644 --- a/packages/CompanionDeviceManager/res/values-hy/strings.xml +++ b/packages/CompanionDeviceManager/res/values-hy/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Ընտրեք <xliff:g id="PROFILE_NAME">%1$s</xliff:g>ը, որը պետք է կառավարվի <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> հավելվածի կողմից"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը կկարողանա փոխազդել ձեր ծանուցումների հետ և կստանա «Հեռախոս», «SMS», «Կոնտակտներ» և «Օրացույց» ծառայությունների թույլտվությունները։"</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը կկարողանա փոխազդել ձեր ծանուցումների հետ և կստանա «Հեռախոս», «SMS», «Կոնտակտներ» և «Օրացույց» ծառայությունների թույլտվությունները։"</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Թույլատրե՞լ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> հավելվածին բացել հավելվածներ"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Թույլ տվեք, որ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> հավելվածը կապի հաստատման դեպքում <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>-ին տրամադրի այս հեռախոսում տեղադրված հավելվածներ հեռակա մուտք գործելու թույլտվություն։"</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Թույլ տվեք, որ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> հավելվածը կապի հաստատման դեպքում <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>-ին տրամադրի այս պլանշետում տեղադրված հավելվածներ հեռակա մուտք գործելու թույլտվություն։"</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Թույլ տվեք, որ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> հավելվածը ինտերնետ կապի հաստատման դեպքում <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>-ին տրամադրի այս սարքում տեղադրված հավելվածներ հեռակա մուտք գործելու թույլտվություն։"</string> + <string name="permission_apps" msgid="6142133265286656158">"Հավելվածներ"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Հեռարձակել հեռախոսի հավելվածները"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Թույլատրեք <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> հավելվածին օգտագործել այս տեղեկությունները ձեր հեռախոսից"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Միջսարքային ծառայություններ"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը ձեր <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> սարքի անունից թույլտվություն է խնդրում՝ ձեր հեռախոսի լուսանկարները, մեդիաֆայլերն ու ծանուցումները տեսնելու համար"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Թույլատրեք <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> հավելվածին օգտագործել այս տեղեկությունները ձեր հեռախոսից"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Ծանուցումներ"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Կարող է կարդալ բոլոր ծանուցումները, ներառյալ տեղեկությունները, օրինակ՝ կոնտակտները, հաղորդագրությունները և լուսանկարները"</string> + <string name="permission_storage" msgid="6831099350839392343">"Լուսանկարներ և մուլտիմեդիա"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play ծառայություններ"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը ձեր <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> սարքի անունից թույլտվություն է խնդրում՝ ձեր սարքերի միջև հավելվածներ հեռարձակելու համար"</string> <string name="profile_name_generic" msgid="6851028682723034988">"սարք"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Թույլատրել"</string> <string name="consent_no" msgid="2640796915611404382">"Չթույլատրել"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Հավելվածների թույլտվությունների տեղափոխում ժամացույց"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Կարգավորման ժամանակ ժամացույցում տեղադրված հավելվածների համար կօգտագործվեն նույն թույլտվությունները, ինչ հեռախոսում։\n\n Այդ թույլտվությունները կարող են ներառել ժամացույցի խոսափողի կամ տեղադրության տվյալների օգտագործումը։"</string> + <string name="consent_back" msgid="2560683030046918882">"Հետ"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> սարքում տա՞լ հավելվածներին նույն թույլտվությունները, ինչ <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> սարքում"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Դրանք կարող են ներառել խոսափողի, տեսախցիկի և տեղադրության տվյալների օգտագործման թույլտվությունները, ինչպես նաև կոնֆիդենցիալ տեղեկությունների օգտագործման այլ թույլտվություններ <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> սարքում։</p> <p>Այդ թույլտվությունները ցանկացած ժամանակ կարելի է փոխել <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> սարքի ձեր կարգավորումներում։</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-in/strings.xml b/packages/CompanionDeviceManager/res/values-in/strings.xml index ef52808cd5ff..6fbdcbeab6a9 100644 --- a/packages/CompanionDeviceManager/res/values-in/strings.xml +++ b/packages/CompanionDeviceManager/res/values-in/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Pilih <xliff:g id="PROFILE_NAME">%1$s</xliff:g> untuk dikelola oleh <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> akan diizinkan berinteraksi dengan notifikasi dan mengakses izin Telepon, SMS, Kontak, dan Kalender."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> akan diizinkan berinteraksi dengan notifikasi dan mengakses izin Telepon, SMS, Kontak, dan Kalender."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Izinkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> men-streaming aplikasi?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Izinkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> memberikan akses jarak jauh ke <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> guna mengakses aplikasi yang diinstal di ponsel ini saat terhubung."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Izinkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> memberikan akses jarak jauh ke <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> guna mengakses aplikasi yang diinstal di tablet ini saat terhubung."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Izinkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> memberikan akses jarak jauh ke <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> guna mengakses aplikasi yang diinstal di perangkat ini saat terhubung."</string> + <string name="permission_apps" msgid="6142133265286656158">"Aplikasi"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Melakukan streaming aplikasi ponsel Anda"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Izinkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> untuk mengakses informasi ini dari ponsel Anda"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Layanan lintas perangkat"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> meminta izin atas nama <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> untuk mengakses foto, media, dan notifikasi ponsel Anda"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Izinkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> mengakses informasi ini dari ponsel Anda"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Notifikasi"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Dapat membaca semua notifikasi, termasuk informasi seperti kontak, pesan, dan foto"</string> + <string name="permission_storage" msgid="6831099350839392343">"Foto dan media"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Layanan Google Play"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> meminta izin atas nama <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> untuk menstreaming aplikasi di antara perangkat Anda"</string> <string name="profile_name_generic" msgid="6851028682723034988">"perangkat"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Izinkan"</string> <string name="consent_no" msgid="2640796915611404382">"Jangan izinkan"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transfer izin aplikasi ke smartwatch"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Untuk mempermudah penyiapan smartwatch, aplikasi yang diinstal di smartwatch selama penyiapan akan menggunakan izin yang sama dengan ponsel.\n\n Izin ini dapat meliputi akses ke mikrofon dan lokasi smartwatch."</string> + <string name="consent_back" msgid="2560683030046918882">"Kembali"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Berikan aplikasi di <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> izin yang sama seperti di <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Ini termasuk akses Mikrofon, Kamera, dan Lokasi, serta izin sensitif lainnya di <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Anda dapat mengubah izin ini kapan saja di Setelan pada <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-is/strings.xml b/packages/CompanionDeviceManager/res/values-is/strings.xml index c0ca2fcf3ba3..035a5a297b21 100644 --- a/packages/CompanionDeviceManager/res/values-is/strings.xml +++ b/packages/CompanionDeviceManager/res/values-is/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Velja <xliff:g id="PROFILE_NAME">%1$s</xliff:g> sem <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> á að stjórna"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> fær aðgang að tilkynningum og heimildum síma, SMS, tengiliða og dagatals."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> fær aðgang að tilkynningum og heimildum síma, SMS, tengiliða og dagatals."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Leyfa <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> að streyma forritum?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Leyfa <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> að veita <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> fjaraðgang að forritum sem eru sett upp í þessum síma þegar tenging er á."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Leyfa <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> að veita <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> fjaraðgang að forritum sem eru sett upp í þessari spjaldtölvu þegar tenging er á."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Leyfa <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> að veita <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> fjaraðgang að forritum sem eru sett upp í þessu tæki þegar tenging er á."</string> + <string name="permission_apps" msgid="6142133265286656158">"Forrit"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Streymdu forritum símans"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Veita <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> aðgang að þessum upplýsingum úr símanum þínum"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Þjónustur á milli tækja"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> sendir beiðni um aðgang að myndum, margmiðlunarefni og tilkynningum símans þíns fyrir hönd <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Veita <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> aðgang að þessum upplýsingum úr símanum þínum"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Tilkynningar"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Getur lesið allar tilkynningar, þar á meðal upplýsingar á borð við tengiliði skilaboð og myndir"</string> + <string name="permission_storage" msgid="6831099350839392343">"Myndir og efni"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Þjónusta Google Play"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> sendir beiðni um heimild fyrir straumspilun forrita á milli tækjanna þinna fyrir hönd <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="profile_name_generic" msgid="6851028682723034988">"tæki"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Leyfa"</string> <string name="consent_no" msgid="2640796915611404382">"Ekki leyfa"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Flytja heimildir forrita yfir í úrið"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Til að auðvelda uppsetningu úrsins munu forrit sem eru sett upp í úrinu við uppsetningu nota sömu heimildir og stilltar eru í símanum.\n\n Þessar heimildir kunna að fela í sér aðgang að hljóðnema og staðsetningu úrsins."</string> + <string name="consent_back" msgid="2560683030046918882">"Til baka"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Veita forritum í <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> sömu heimildir og í <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Þetta kann að fela í sér aðgang að hljóðnema, myndavél og staðsetningu og aðrar heimildir fyrir viðkvæmu efni í <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Hægt er að breyta þessum heimildum hvenær sem er í stillingunum í <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-it/strings.xml b/packages/CompanionDeviceManager/res/values-it/strings.xml index 5f88b7a68432..3bf2bcd7187b 100644 --- a/packages/CompanionDeviceManager/res/values-it/strings.xml +++ b/packages/CompanionDeviceManager/res/values-it/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Scegli un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> che sia gestito da <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"L\'app <xliff:g id="APP_NAME">%1$s</xliff:g> potrà interagire con le tue notifiche e accedere alle autorizzazioni Telefono, SMS, Contatti e Calendario."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"L\'app <xliff:g id="APP_NAME">%1$s</xliff:g> potrà interagire con le tue notifiche e accedere alle autorizzazioni Telefono, SMS, Contatti e Calendario."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Vuoi consentire all\'app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> di riprodurre applicazioni in streaming?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Consenti all\'app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> di fornire l\'accesso remoto a <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> per accedere alle applicazioni installate su questo telefono quando è connesso."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Consenti all\'app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> di fornire l\'accesso remoto a <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> per accedere alle applicazioni installate su questo tablet quando è connesso."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Consenti all\'app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> di fornire l\'accesso remoto a <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> per accedere alle applicazioni installate su questo dispositivo quando è connesso."</string> + <string name="permission_apps" msgid="6142133265286656158">"App"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Trasmetti in streaming le app del tuo telefono"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Consenti all\'app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> di accedere a queste informazioni dal tuo telefono"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Servizi cross-device"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> richiede per conto del tuo <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> l\'autorizzazione ad accedere a foto, contenuti multimediali e notifiche del telefono"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Consenti a <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> di accedere a questa informazione dal tuo telefono"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Notifiche"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Puoi leggere tutte le notifiche, incluse le informazioni come contatti, messaggi e foto"</string> + <string name="permission_storage" msgid="6831099350839392343">"Foto e contenuti multimediali"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play Services"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> richiede per conto del tuo <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> l\'autorizzazione a trasmettere app in streaming tra i dispositivi"</string> <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Consenti"</string> <string name="consent_no" msgid="2640796915611404382">"Non consentire"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Trasferisci le autorizzazioni app all\'orologio"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Per facilitare la configurazione dell\'orologio, le app installate su quest\'ultimo durante la configurazione useranno le stesse autorizzazioni delle app sul telefono.\n\n Queste autorizzazioni potrebbero includere l\'accesso al microfono e alla posizione dell\'orologio."</string> + <string name="consent_back" msgid="2560683030046918882">"Indietro"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Vuoi dare alle app su <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> le stesse autorizzazioni che hai dato su <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Potrebbero essere incluse le autorizzazioni di accesso al microfono, alla fotocamera e alla posizione, nonché altre autorizzazioni sensibili su <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Puoi cambiare queste autorizzazioni in qualsiasi momento nelle Impostazioni su <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-iw/strings.xml b/packages/CompanionDeviceManager/res/values-iw/strings.xml index 4a811f0aef9d..b8794fefe0bc 100644 --- a/packages/CompanionDeviceManager/res/values-iw/strings.xml +++ b/packages/CompanionDeviceManager/res/values-iw/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"בחירת <xliff:g id="PROFILE_NAME">%1$s</xliff:g> לניהול באמצעות <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> תוכל לבצע פעולות בהתראות ותקבל הרשאות גישה לטלפון, ל-SMS לאנשי הקשר וליומן."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> תוכל לבצע פעולות בהתראות ותקבל הרשאות גישה לטלפון, ל-SMS לאנשי הקשר וליומן."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"לאפשר לאפליקציה <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> לשדר אפליקציות?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"האפליקציה <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> יכולה לספק ל-<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> גישה מרחוק כדי לגשת לאפליקציות שמותקנות בטלפון הזה כשיש חיבור."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"האפליקציה <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> יכולה לספק ל-<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> גישה מרחוק כדי לגשת לאפליקציות שמותקנות בטאבלט הזה כשיש חיבור."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"האפליקציה <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> יכולה לספק למכשיר <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> גישה מרחוק כדי לגשת לאפליקציות שמותקנות במכשיר הזה כשיש חיבור."</string> + <string name="permission_apps" msgid="6142133265286656158">"אפליקציות"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"שידור אפליקציות מהטלפון"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"מתן אישור לאפליקציה <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> לגשת למידע הזה מהטלפון שלך"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"שירותים למספר מכשירים"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> מבקשת הרשאה עבור ה‑<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> כדי לגשת לתמונות, למדיה ולהתראות בטלפון שלך"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"מתן אישור לאפליקציה <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> לגשת למידע הזה מהטלפון שלך"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"התראות"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"גישת קריאה לכל ההתראות, כולל מידע כמו אנשי קשר, הודעות ותמונות."</string> + <string name="permission_storage" msgid="6831099350839392343">"תמונות ומדיה"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play Services"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> מבקשת הרשאה עבור ה‑<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> כדי לשדר אפליקציות בין המכשירים שלך"</string> <string name="profile_name_generic" msgid="6851028682723034988">"מכשיר"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"יש אישור"</string> <string name="consent_no" msgid="2640796915611404382">"אין אישור"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"העברת ההרשאות הניתנות לאפליקציות אל השעון שלך"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"כדי לפשט את הגדרת השעון, אפליקציות שמותקנות במהלך ההגדרה יקבלו את אותן הרשאות שניתנו בטלפון.\n\n ההרשאות האלה עשויות לכלול גישה למיקרופון ולמיקום של השעון."</string> + <string name="consent_back" msgid="2560683030046918882">"חזרה"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"האם לתת לאפליקציות ב-<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong>את אותן הרשאות כמו ב-<strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>ההרשאות עשויות לכלול גישה למיקרופון, למצלמה ולמיקום, וכן גישה למידע רגיש אחר ב-</strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p&gt; <p>אפשר לשנות את ההרשאות האלה בכל שלב בהגדרות של <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-ja/strings.xml b/packages/CompanionDeviceManager/res/values-ja/strings.xml index 5e8d544d9b6a..579907f097ff 100644 --- a/packages/CompanionDeviceManager/res/values-ja/strings.xml +++ b/packages/CompanionDeviceManager/res/values-ja/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> の管理対象となる<xliff:g id="PROFILE_NAME">%1$s</xliff:g>の選択"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> は通知を使用でき、電話、SMS、連絡先、カレンダーの権限にもアクセスできるようになります。"</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> は通知を使用でき、電話、SMS、連絡先、カレンダーの権限にもアクセスできるようになります。"</string> - <string name="title_app_streaming" msgid="4459136600249308574">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> にアプリのストリーミングを許可しますか?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"インターネット接続時に <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> がスマートフォン内にインストールされているアプリにリモートでアクセスすることを <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> に許可します。"</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"インターネット接続時に <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> がタブレット内にインストールされているアプリにリモートでアクセスすることを <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> に許可します。"</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"インターネット接続時に <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> がデバイス内にインストールされているアプリにリモートでアクセスすることを <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> に許可します。"</string> + <string name="permission_apps" msgid="6142133265286656158">"アプリ"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"スマートフォンのアプリのストリーミング"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"スマートフォンのこの情報へのアクセスを <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> に許可"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"クロスデバイス サービス"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> が <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> に代わってスマートフォンの写真、メディア、通知にアクセスする権限をリクエストしています"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"このスマートフォンからの情報へのアクセスを <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> に許可"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"通知"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"連絡先、メッセージ、写真に関する情報を含め、すべての通知を読み取ることができます"</string> + <string name="permission_storage" msgid="6831099350839392343">"写真とメディア"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play 開発者サービス"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> が <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> に代わってデバイス間でアプリをストリーミングする権限をリクエストしています"</string> <string name="profile_name_generic" msgid="6851028682723034988">"デバイス"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"許可"</string> <string name="consent_no" msgid="2640796915611404382">"許可しない"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"スマートウォッチへのアプリの権限の移行"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"スマートウォッチのセットアップを簡単にするため、セットアップ時にスマートウォッチにインストールされたアプリに、スマートフォンと同じ権限が適用されます。\n\n これらの権限には、スマートウォッチのマイクや位置情報へのアクセス権も含まれることがあります。"</string> + <string name="consent_back" msgid="2560683030046918882">"戻る"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> のアプリに <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> の場合と同じ権限を付与しますか?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>これには、<strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> のマイク、カメラ、位置情報へのアクセスや、その他の機密情報に関わる権限が含まれる可能性があります。</p> <p>これらの権限は <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> の [設定] でいつでも変更できます。</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-ka/strings.xml b/packages/CompanionDeviceManager/res/values-ka/strings.xml index 3b179bf237dd..7b15ad1a6bfe 100644 --- a/packages/CompanionDeviceManager/res/values-ka/strings.xml +++ b/packages/CompanionDeviceManager/res/values-ka/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"აირჩიეთ <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, რომელიც უნდა მართოს <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>-მა"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> შეძლებს თქვენს შეტყობინებებთან ინტერაქციას და თქვენი ტელეფონის, SMS-ების, კონტაქტებისა და კალენდრის ნებართვებზე წვდომას."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> შეძლებს თქვენს შეტყობინებებთან ინტერაქციას და თქვენი ტელეფონის, SMS-ების, კონტაქტებისა და კალენდრის ნებართვებზე წვდომას."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"გსურთ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-ს მისცეთ აპების სტრიმინგის საშუალება?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"მიეცით <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-ს საშუალება, <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>-ისთვის დაუშვას დისტანციური წვდომა ამ ტელეფონზე დაინსტალირებულ აპებზე მასთან დაკავშირებისას."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"მიეცით <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-ს საშუალება, <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>-ისთვის დაუშვას დისტანციური წვდომა ამ ტაბლეტზე დაინსტალირებულ აპებზე მასთან დაკავშირებისას."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"მიეცით <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-ს საშუალება, <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>-ისთვის დაუშვას დისტანციური წვდომა ამ მოწყობილობაზე დაინსტალირებულ აპებზე მასთან დაკავშირებისას."</string> + <string name="permission_apps" msgid="6142133265286656158">"აპები"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"თქვენი ტელეფონის აპების სტრიმინგი"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"ნება დართეთ, რომ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> აპს ჰქონდეს ამ ინფორმაციაზე წვდომა თქვენი ტელეფონიდან"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"მოწყობილობათშორისი სერვისები"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> ითხოვს უფლებას თქვენი <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-ის სახელით, რომ წვდომა ჰქონდეს თქვენი ტელეფონის ფოტოებზე, მედიასა და შეტყობინებებზე"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"ნება დართეთ, რომ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> აპს ჰქონდეს ამ ინფორმაციაზე წვდომა თქვენი ტელეფონიდან"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"შეტყობინებები"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"შეუძლია წაიკითხოს ყველა შეტყობინება, მათ შორის ისეთი ინფორმაცია, როგორიცაა კონტაქტები, ტექსტური შეტყობინებები და ფოტოები"</string> + <string name="permission_storage" msgid="6831099350839392343">"ფოტოები და მედია"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play services"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> ითხოვს უფლებას თქვენი <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-ის სახელით, რომ მოწყობილობებს შორის სტრიმინგი შეძლოს"</string> <string name="profile_name_generic" msgid="6851028682723034988">"მოწყობილობა"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"დაშვება"</string> <string name="consent_no" msgid="2640796915611404382">"არ დაიშვას"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"აპის ნებართვების საათისთვის გადაცემა"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"საათის დაყენების გასამარტივებლად თქვენს საათში დაინსტალირებული აპები იმავე ნებართვებს გამოიყენებს, რასაც ტელეფონზე იყენებს.\n\n ეს ნებართვები, შესაძლოა, მოიცავდეს თქვენი საათის მიკროფონსა და მდებარეობაზე წვდომას."</string> + <string name="consent_back" msgid="2560683030046918882">"უკან"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"გსურთ აპებს <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong>-ზე იგივე ნებართვები მიანიჭოთ, როგორიც აქვს <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>-ზე?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>აღნიშნული შეიძლება მოიცავდეს მიკროფონზე, კამერასა და მდებარეობაზე წვდომას თუ სხვა ნებართვას სენსიტიურ ინფორმაციაზე <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>-ში.</p> <p>ამ ნებართვების შეცვლა ნებისმიერ დროს შეგიძლიათ თქვენი პარამეტრებიდან <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>-ში.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-kk/strings.xml b/packages/CompanionDeviceManager/res/values-kk/strings.xml index a7efb15ed0be..c1129bbbe246 100644 --- a/packages/CompanionDeviceManager/res/values-kk/strings.xml +++ b/packages/CompanionDeviceManager/res/values-kk/strings.xml @@ -22,18 +22,28 @@ <string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> арқылы басқарылатын <xliff:g id="PROFILE_NAME">%1$s</xliff:g> құрылғысын таңдаңыз"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасы хабарландыруларды, телефонды, SMS хабардарын, контактілерді және күнтізбе рұқсаттарын пайдалана алады."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасы хабарландыруларды, телефонды, SMS хабардарын, контактілерді және күнтізбе рұқсаттарын пайдалана алады."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> қолданбасына қолданбаларды трансляциялауға рұқсат етілсін бе?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> желіге қосылған кезде, <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> қолданбасына осы телефонға орнатылған қолданбаларды қашықтан пайдалануына рұқсат етіңіз."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> желіге қосылған кезде, <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> қолданбасына осы планшетке орнатылған қолданбаларды қашықтан пайдалануына рұқсат етіңіз."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> желіге қосылған кезде, <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> қолданбасына осы құрылғыға орнатылған қолданбаларды қашықтан пайдалануына рұқсат етіңіз."</string> + <string name="permission_apps" msgid="6142133265286656158">"Қолданбалар"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Телефон қолданбаларын трансляциялайды."</string> + <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> қолданбасына телефоныңыздағы осы ақпаратты пайдалануға рұқсат беріңіз."</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Аралық құрылғы қызметтері"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасы <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> атынан телефондағы фотосуреттерді, медиафайлдар мен хабарландыруларды пайдалану үшін рұқсат сұрайды."</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> қолданбасына телефоныңыздағы осы ақпаратты пайдалануға рұқсат беріңіз."</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Хабарландырулар"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Барлық хабарландыруды, соның ішінде контактілер, хабарлар және фотосуреттер сияқты ақпаратты оқи алады."</string> + <string name="permission_storage" msgid="6831099350839392343">"Фотосуреттер мен медиафайлдар"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play қызметтері"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасы <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> атынан құрылғылар арасында қолданбалар трансляциялау үшін рұқсат сұрайды."</string> <string name="profile_name_generic" msgid="6851028682723034988">"құрылғы"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Рұқсат беру"</string> <string name="consent_no" msgid="2640796915611404382">"Рұқсат бермеу"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Қолданба рұқсаттарын сағатқа ауыстыру"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Реттеу кезінде сағатқа орнатылған қолданбалар телефондағыдай рұқсаттарды пайдаланады. Осылайша сағат оңай реттеледі.\n\n Бұл рұқсаттар сағаттың микрофоны мен геодерегін пайдалануды қамтиды."</string> + <string name="consent_back" msgid="2560683030046918882">"Артқа"</string> + <!-- no translation found for permission_sync_confirmation_title (4409622174437248702) --> + <skip /> + <!-- no translation found for permission_sync_summary (4866838188678457084) --> + <skip /> </resources> diff --git a/packages/CompanionDeviceManager/res/values-km/strings.xml b/packages/CompanionDeviceManager/res/values-km/strings.xml index b18586316289..3e2ec4c84323 100644 --- a/packages/CompanionDeviceManager/res/values-km/strings.xml +++ b/packages/CompanionDeviceManager/res/values-km/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"ជ្រើសរើស <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ដើម្បីឱ្យស្ថិតក្រោមការគ្រប់គ្រងរបស់ <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> នឹងត្រូវបានអនុញ្ញាតឱ្យធ្វើអន្តរកម្មជាមួយការជូនដំណឹងរបស់អ្នក និងចូលប្រើការអនុញ្ញាតប្រតិទិន, ទូរសព្ទ, SMS និងទំនាក់ទំនងរបស់អ្នក។"</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> នឹងត្រូវបានអនុញ្ញាតឱ្យធ្វើអន្តរកម្មជាមួយការជូនដំណឹងរបស់អ្នក និងចូលប្រើការអនុញ្ញាតប្រតិទិន, ទូរសព្ទ, SMS និងទំនាក់ទំនងរបស់អ្នក។"</string> - <string name="title_app_streaming" msgid="4459136600249308574">"អនុញ្ញាតឱ្យ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ផ្សាយកម្មវិធីឬ?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"អនុញ្ញាតឱ្យ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ផ្ដល់ការចូលប្រើពីចម្ងាយដល់ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ដើម្បីចូលប្រើកម្មវិធី ដែលបានដំឡើងនៅលើទូរសព្ទនេះ នៅពេលភ្ជាប់អ៊ីនធឺណិត។"</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"អនុញ្ញាតឱ្យ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ផ្ដល់ការចូលប្រើពីចម្ងាយដល់ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ដើម្បីចូលប្រើកម្មវិធី ដែលបានដំឡើងនៅលើថេប្លេតនេះ នៅពេលភ្ជាប់អ៊ីនធឺណិត។"</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"អនុញ្ញាតឱ្យ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ផ្ដល់ការចូលប្រើពីចម្ងាយដល់ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ដើម្បីចូលប្រើកម្មវិធី ដែលបានដំឡើងនៅលើឧបករណ៍នេះ នៅពេលភ្ជាប់អ៊ីនធឺណិត។"</string> + <string name="permission_apps" msgid="6142133265286656158">"កម្មវិធី"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"បញ្ចាំងកម្មវិធីរបស់ទូរសព្ទអ្នក"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"អនុញ្ញាតឱ្យ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ចូលប្រើព័ត៌មាននេះពីទូរសព្ទរបស់អ្នក"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"សេវាកម្មឆ្លងកាត់ឧបករណ៍"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> កំពុងស្នើសុំការអនុញ្ញាតជំនួសឱ្យ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> របស់អ្នក ដើម្បីចូលប្រើរូបថត មេឌៀ និងការជូនដំណឹងរបស់ទូរសព្ទអ្នក"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"អនុញ្ញាតឱ្យ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ចូលមើលព័ត៌មាននេះពីទូរសព្ទរបស់អ្នក"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"ការជូនដំណឹង"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"អាចអានការជូនដំណឹងទាំងអស់ រួមទាំងព័ត៌មានដូចជាទំនាក់ទំនង សារ និងរូបថត"</string> + <string name="permission_storage" msgid="6831099350839392343">"រូបថត និងមេឌៀ"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"សេវាកម្ម Google Play"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> កំពុងស្នើសុំការអនុញ្ញាតជំនួសឱ្យ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> របស់អ្នក ដើម្បីបញ្ចាំងកម្មវិធីរវាងឧបករណ៍របស់អ្នក"</string> <string name="profile_name_generic" msgid="6851028682723034988">"ឧបករណ៍"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"អនុញ្ញាត"</string> <string name="consent_no" msgid="2640796915611404382">"កុំអនុញ្ញាត"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"ផ្ទេរការអនុញ្ញាតកម្មវិធីទៅនាឡិការបស់អ្នក"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"ដើម្បីជួយឱ្យការរៀបចំនាឡិការបស់អ្នកកាន់តែងាយស្រួល កម្មវិធីដែលបានដំឡើងនៅលើនាឡិការបស់អ្នកអំឡុងពេលរៀបចំនឹងប្រើការអនុញ្ញាតដូចគ្នានឹងទូរសព្ទរបស់អ្នកដែរ។\n\n ការអនុញ្ញាតទាំងនេះអាចរួមបញ្ចូលសិទ្ធិចូលប្រើទីតាំង និងមីក្រូហ្វូនរបស់នាឡិកាអ្នក។"</string> + <string name="consent_back" msgid="2560683030046918882">"ថយក្រោយ"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"ផ្ដល់ការអនុញ្ញាតឱ្យកម្មវិធីនៅលើ <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> ដូចនៅលើ <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> ឬ?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>សកម្មភាពនេះអាចរួមបញ្ចូលការចូលប្រើទីតាំង កាមេរ៉ា និងមីក្រូហ្វូន និងការអនុញ្ញាតដែលមានលក្ខណៈរសើបផ្សេងទៀតនៅលើ <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>។</p> <p>អ្នកអាចប្ដូរការអនុញ្ញាតទាំងនេះបានគ្រប់ពេលវេលានៅក្នុងការកំណត់នៅលើ <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>។</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-kn/strings.xml b/packages/CompanionDeviceManager/res/values-kn/strings.xml index 64576ce8aec8..f940b70c6738 100644 --- a/packages/CompanionDeviceManager/res/values-kn/strings.xml +++ b/packages/CompanionDeviceManager/res/values-kn/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> ಮೂಲಕ ನಿರ್ವಹಿಸಬೇಕಾದ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ಅನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"ನಿಮ್ಮ ಅಧಿಸೂಚನೆಗಳೊಂದಿಗೆ ಸಂವಹನ ನಡೆಸಲು ಮತ್ತು ನಿಮ್ಮ ಫೋನ್, SMS, ಸಂಪರ್ಕಗಳು ಮತ್ತು Calendar ಅನುಮತಿಗಳನ್ನು ಪ್ರವೇಶಿಸಲು <xliff:g id="APP_NAME">%1$s</xliff:g> ಗೆ ಅನುಮತಿಸಲಾಗುತ್ತದೆ."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"ನಿಮ್ಮ ಅಧಿಸೂಚನೆಗಳೊಂದಿಗೆ ಸಂವಹನ ನಡೆಸಲು ಮತ್ತು ನಿಮ್ಮ ಫೋನ್, SMS, ಸಂಪರ್ಕಗಳು ಮತ್ತು Calendar ಅನುಮತಿಗಳನ್ನು ಪ್ರವೇಶಿಸಲು <xliff:g id="APP_NAME">%1$s</xliff:g> ಗೆ ಅನುಮತಿಸಲಾಗುತ್ತದೆ."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"ಆ್ಯಪ್ಗಳನ್ನು ಸ್ಟ್ರೀಮ್ ಮಾಡಲು <xliff:g id="APP_NAME">%1$s</xliff:g> ಗೆ ಅನುಮತಿಸಿ?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"ಕನೆಕ್ಟ್ ಆದಾಗ ಈ ಫೋನ್ನಲ್ಲಿ ಇನ್ಸ್ಟಾಲ್ ಮಾಡಲಾದ ಆ್ಯಪ್ಗಳನ್ನು ಪ್ರವೇಶಿಸುವುದಕ್ಕಾಗಿ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ಗೆ ರಿಮೋಟ್ ಪ್ರವೇಶವನ್ನು ಒದಗಿಸಲು <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ಗೆ ಅನುಮತಿಸಿ."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"ಕನೆಕ್ಟ್ ಆದಾಗ ಈ ಟ್ಯಾಬ್ಲೆಟ್ನಲ್ಲಿ ಇನ್ಸ್ಟಾಲ್ ಮಾಡಲಾದ ಆ್ಯಪ್ಗಳನ್ನು ಪ್ರವೇಶಿಸುವುದಕ್ಕಾಗಿ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ಗೆ ರಿಮೋಟ್ ಪ್ರವೇಶವನ್ನು ಒದಗಿಸಲು <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ಗೆ ಅನುಮತಿಸಿ."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"ಕನೆಕ್ಟ್ ಆದಾಗ ಈ ಸಾಧನದಲ್ಲಿ ಇನ್ಸ್ಟಾಲ್ ಮಾಡಲಾದ ಆ್ಯಪ್ಗಳನ್ನು ಪ್ರವೇಶಿಸುವುದಕ್ಕಾಗಿ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ಗೆ ರಿಮೋಟ್ ಪ್ರವೇಶವನ್ನು ಒದಗಿಸಲು <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ಗೆ ಅನುಮತಿಸಿ."</string> + <string name="permission_apps" msgid="6142133265286656158">"ಆ್ಯಪ್ಗಳು"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"ನಿಮ್ಮ ಫೋನ್ನ ಆ್ಯಪ್ಗಳನ್ನು ಸ್ಟ್ರೀಮ್ ಮಾಡಿ"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"ನಿಮ್ಮ ಫೋನ್ ಮೂಲಕ ಈ ಮಾಹಿತಿಯನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ಗೆ ಅನುಮತಿಸಿ"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"ಕ್ರಾಸ್-ಸಾಧನ ಸೇವೆಗಳು"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"ನಿಮ್ಮ ಫೋನ್ನ ಫೋಟೋಗಳು, ಮೀಡಿಯಾ ಮತ್ತು ಅಧಿಸೂಚನೆಗಳನ್ನು ಪ್ರವೇಶಿಸಲು ನಿಮ್ಮ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ನ ಪರವಾಗಿ <xliff:g id="APP_NAME">%1$s</xliff:g> ಅನುಮತಿಯನ್ನು ವಿನಂತಿಸಿಕೊಳ್ಳುತ್ತಿದೆ"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"ನಿಮ್ಮ ಫೋನ್ ಮೂಲಕ ಈ ಮಾಹಿತಿಯನ್ನು ಪ್ರವೇಶಿಸಲು <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ಗೆ ಅನುಮತಿಸಿ"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"ಅಧಿಸೂಚನೆಗಳು"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"ಸಂಪರ್ಕಗಳು, ಸಂದೇಶಗಳು ಮತ್ತು ಫೋಟೋಗಳಂತಹ ಮಾಹಿತಿಯನ್ನು ಒಳಗೊಂಡಂತೆ ಎಲ್ಲಾ ಅಧಿಸೂಚನೆಗಳನ್ನು ಓದಬಹುದು"</string> + <string name="permission_storage" msgid="6831099350839392343">"ಫೋಟೋಗಳು ಮತ್ತು ಮಾಧ್ಯಮ"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play ಸೇವೆಗಳು"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"ನಿಮ್ಮ ಸಾಧನಗಳ ನಡುವೆ ಆ್ಯಪ್ಗಳನ್ನು ಸ್ಟ್ರೀಮ್ ಮಾಡಲು ನಿಮ್ಮ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ನ ಪರವಾಗಿ <xliff:g id="APP_NAME">%1$s</xliff:g> ಅನುಮತಿಯನ್ನು ವಿನಂತಿಸಿಕೊಳ್ಳುತ್ತಿದೆ"</string> <string name="profile_name_generic" msgid="6851028682723034988">"ಸಾಧನ"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"ಅನುಮತಿಸಿ"</string> <string name="consent_no" msgid="2640796915611404382">"ಅನುಮತಿಸಬೇಡಿ"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"ಆ್ಯಪ್ ಅನುಮತಿಗಳನ್ನು ನಿಮ್ಮ ವಾಚ್ಗೆ ವರ್ಗಾವಣೆ ಮಾಡಿ"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"ನಿಮ್ಮ ವಾಚ್ ಸೆಟಪ್ ಮಾಡುವುದನ್ನು ಸುಲಭವಾಗಿಸಲು, ಸೆಟಪ್ನ ಸಮಯದಲ್ಲಿ ನಿಮ್ಮ ವಾಚ್ನಲ್ಲಿ ಇನ್ಸ್ಟಾಲ್ ಮಾಡಿದ ಆ್ಯಪ್ಗಳು, ನಿಮ್ಮ ಫೋನ್ನಲ್ಲಿನ ಅನುಮತಿಗಳನ್ನೇ ಬಳಸಿಕೊಳ್ಳುತ್ತವೆ.\n\n ಈ ಅನುಮತಿಗಳು ನಿಮ್ಮ ವಾಚ್ನ ಮೈಕ್ರೊಫೋನ್ ಮತ್ತು ಸ್ಥಳದ ಪ್ರವೇಶವನ್ನು ಒಳಗೊಳ್ಳಬಹುದು."</string> + <string name="consent_back" msgid="2560683030046918882">"ಹಿಂದೆ"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"</strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> ನಲ್ಲಿನ ಅನುಮತಿಗಳನ್ನೇ </strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> ನಲ್ಲಿನ ಆ್ಯಪ್ಗಳಿಗೆ ನೀಡಬೇಕೆ?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>ಇದು <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> ನಲ್ಲಿನ ಮೈಕ್ರೊಫೋನ್, ಕ್ಯಾಮರಾ ಮತ್ತು ಸ್ಥಳ ಆ್ಯಕ್ಸೆಸ್ ಹಾಗೂ ಇತರ ಸೂಕ್ಷ್ಮ ಅನುಮತಿಗಳನ್ನು ಹೊಂದಿರಬಹುದು<p></p> <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> ನಲ್ಲಿನ ನಿಮ್ಮ ಸೆಟ್ಟಿಂಗ್ಗಳಲ್ಲಿ ನೀವು ಈ ಅನುಮತಿಗಳನ್ನು ಯಾವಾಗ ಬೇಕಾದರೂ ಬದಲಾಯಿಸಬಹುದು.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-ko/strings.xml b/packages/CompanionDeviceManager/res/values-ko/strings.xml index 5bf8eb4ae6ac..2c7d8dac6870 100644 --- a/packages/CompanionDeviceManager/res/values-ko/strings.xml +++ b/packages/CompanionDeviceManager/res/values-ko/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>에서 관리할 <xliff:g id="PROFILE_NAME">%1$s</xliff:g>을(를) 선택"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 알림과 상호작용하고 전화, SMS, 연락처, 캘린더 권한에 액세스할 수 있게 됩니다."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 알림과 상호작용하고 전화, SMS, 연락처, 캘린더 권한에 액세스할 수 있게 됩니다."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>에서 애플리케이션을 스트리밍하도록 허용하시겠습니까?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"연결 시 <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>에서 <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>에 이 휴대전화에 설치된 애플리케이션에 원격으로 액세스할 수 있는 권한을 제공하도록 허용합니다."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"연결 시 <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>에서 <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>에 이 태블릿에 설치된 애플리케이션에 원격으로 액세스할 수 있는 권한을 제공하도록 허용합니다."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"연결 시 <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>에서 <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>에 이 기기에 설치된 애플리케이션에 원격으로 액세스할 수 있는 권한을 제공하도록 허용합니다."</string> + <string name="permission_apps" msgid="6142133265286656158">"앱"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"휴대전화의 앱을 스트리밍합니다."</string> + <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> 앱이 휴대전화에서 이 정보에 액세스하도록 허용합니다."</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"교차 기기 서비스"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> 대신 휴대전화의 사진, 미디어, 알림에 액세스할 수 있는 권한을 요청하고 있습니다."</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> 앱이 휴대전화에서 이 정보에 액세스하도록 허용합니다."</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"알림"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"연락처, 메시지, 사진 등의 정보를 포함한 모든 알림을 읽을 수 있습니다."</string> + <string name="permission_storage" msgid="6831099350839392343">"사진 및 미디어"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play 서비스"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> 대신 기기 간에 앱을 스트리밍할 수 있는 권한을 요청하고 있습니다."</string> <string name="profile_name_generic" msgid="6851028682723034988">"기기"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"허용"</string> <string name="consent_no" msgid="2640796915611404382">"허용 안함"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"앱 권한을 시계로 이전"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"시계를 더 쉽게 설정하기 위해 설정하는 동안 시계에 설치된 앱에서 휴대전화와 동일한 권한을 사용합니다.\n\n 이러한 권한에는 시계의 마이크 및 위치 정보에 대한 액세스가 포함될 수 있습니다."</string> + <string name="consent_back" msgid="2560683030046918882">"뒤"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong>에 설치된 앱에 <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>에 설치된 앱과 동일한 권한을 부여하시겠습니까?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>여기에는 <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>에서 허용했던 마이크, 카메라, 위치 정보 액세스 권한 및 기타 민감한 권한이 포함될 수 있습니다.</p> <p>언제든지 <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>의 설정에서 이러한 권한을 변경할 수 있습니다.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-ky/strings.xml b/packages/CompanionDeviceManager/res/values-ky/strings.xml index 714dc9365bd6..0311621d89aa 100644 --- a/packages/CompanionDeviceManager/res/values-ky/strings.xml +++ b/packages/CompanionDeviceManager/res/values-ky/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"<xliff:g id="PROFILE_NAME">%1$s</xliff:g> <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> тарабынан башкарылсын"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> билдирмелериңизди көрүп, телефонуңуздун, SMS билдирүүлөрүңүздүн, байланыштарыңыздын жана жылнаамаңыздын уруксаттарын пайдалана алат."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> билдирмелериңизди көрүп, телефонуңуздун, SMS билдирүүлөрүңүздүн, байланыштарыңыздын жана жылнаамаңыздын уруксаттарын пайдалана алат."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> колдонмосуна колдонмолорду алып ойнотууга уруксат бересизби?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> колдонмосуна Интернетке туташкан <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> телефонундагы колдонмолорго алыстан кирүү мүмкүнчүлүгүн бериңиз."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> колдонмосуна Интернетке туташкан <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> планшетиндеги колдонмолорго алыстан кирүү мүмкүнчүлүгүн бериңиз."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> колдонмосуна Интернетке туташкан <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> түзмөгүндөгү колдонмолорго алыстан кирүү мүмкүнчүлүгүн бериңиз."</string> + <string name="permission_apps" msgid="6142133265286656158">"Колдонмолор"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Телефондогу колдонмолорду алып ойнотуу"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> колдонмосуна телефонуңуздагы ушул маалыматты көрүүгө уруксат бериңиз"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Түзмөктөр аралык кызматтар"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосу <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> түзмөгүңүздүн атынан телефондогу сүрөттөрдү, медианы жана билдирмелерди колдонууга уруксат сурап жатат"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> колдонмосуна телефонуңуздагы ушул маалыматты көрүүгө уруксат бериңиз"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Билдирмелер"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Бардык билдирмелерди, анын ичинде байланыштар, билдирүүлөр жана сүрөттөр сыяктуу маалыматты окуй алат"</string> + <string name="permission_storage" msgid="6831099350839392343">"Сүрөттөр жана медиа"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play кызматтары"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосу <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> түзмөгүңүздүн атынан түзмөктөрүңүздүн ортосунда колдонмолорду тышкы экранга чыгарууга уруксат сурап жатат"</string> <string name="profile_name_generic" msgid="6851028682723034988">"түзмөк"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Уруксат берүү"</string> <string name="consent_no" msgid="2640796915611404382">"Уруксат берилбесин"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Колдонмонун уруксаттарын саатка өткөрүү"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Сааттын жөндөлүшүн жеңилдетүү үчүн жөндөө учурунда саатыңызга орнотулган колдонмолор телефонуңуздагы уруксаттарды колдонот.\n\n Мындай уруксаттарга саатыңыздын микрофонун же жайгашкан жерин колдонуу кириши мүмкүн."</string> + <string name="consent_back" msgid="2560683030046918882">"Артка"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> түзмөгүнө да <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> түзмөгүнө берилген уруксаттар берилсинби?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Бул уруксаттарга микрофонго, камерага жана жайгашкан жерге кирүү мүмкүнчүлүгү жана <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> түзмөгүндөгү башка купуя маалыматты көрүүгө уруксаттар кириши мүмкүн.</p> <p>Бул уруксаттарды каалаган убакта <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> түзмөгүндөгү Жөндөөлөрдөн өзгөртө аласыз.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-lo/strings.xml b/packages/CompanionDeviceManager/res/values-lo/strings.xml index 95cab696240f..cd22d985f70a 100644 --- a/packages/CompanionDeviceManager/res/values-lo/strings.xml +++ b/packages/CompanionDeviceManager/res/values-lo/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"ເລືອກ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ເພື່ອໃຫ້ຖືກຈັດການໂດຍ <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ຈະໄດ້ຮັບອະນຸຍາດໃຫ້ໂຕ້ຕອບກັບການແຈ້ງເຕືອນຂອງທ່ານ ແລະ ເຂົ້າເຖິງການອະນຸຍາດໂທລະສັບ, SMS, ລາຍຊື່ຜູ້ຕິດຕໍ່ ແລະ ປະຕິທິນຂອງທ່ານໄດ້."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ຈະໄດ້ຮັບອະນຸຍາດໃຫ້ໂຕ້ຕອບກັບການແຈ້ງເຕືອນຂອງທ່ານ ແລະ ເຂົ້າເຖິງການອະນຸຍາດໂທລະສັບ, SMS, ລາຍຊື່ຜູ້ຕິດຕໍ່ ແລະ ປະຕິທິນຂອງທ່ານໄດ້."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"ອະນຸຍາດໃຫ້ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ສະຕຣີມແອັບພລິເຄຊັນໄດ້ບໍ?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"ໃຫ້ສິດ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ເພື່ອເຂົ້າເຖິງ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ຈາກໄລຍະໄກເພື່ອເຂົ້າເຖິງແອັບພລິເຄຊັນທີ່ຕິດຕັ້ງຢູ່ໂທລະສັບນີ້ເມື່ອເຊື່ອມຕໍ່ແລ້ວ."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"ໃຫ້ສິດ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ເພື່ອເຂົ້າເຖິງ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ຈາກໄລຍະໄກເພື່ອເຂົ້າເຖິງແອັບພລິເຄຊັນທີ່ຕິດຕັ້ງຢູ່ແທັບເລັດນີ້ເມື່ອເຊື່ອມຕໍ່ແລ້ວ."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"ໃຫ້ສິດ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ເພື່ອເຂົ້າເຖິງ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ຈາກໄລຍະໄກເພື່ອເຂົ້າເຖິງແອັບພລິເຄຊັນທີ່ຕິດຕັ້ງຢູ່ອຸປະກອນນີ້ເມື່ອເຊື່ອມຕໍ່ແລ້ວ."</string> + <string name="permission_apps" msgid="6142133265286656158">"ແອັບ"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"ສະຕຣີມແອັບຂອງໂທລະສັບທ່ານ"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"ອະນຸຍາດ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ໃຫ້ເຂົ້າເຖິງຂໍ້ມູນນີ້ຈາກໂທລະສັບຂອງທ່ານໄດ້"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"ບໍລິການຂ້າມອຸປະກອນ"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> ກຳລັງຮ້ອງຂໍການອະນຸຍາດໃນນາມຂອງ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ເພື່ອເຂົ້າເຖິງຮູບພາບ, ມີເດຍ ແລະ ການແຈ້ງເຕືອນຂອງໂທລະສັບທ່ານ"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"ອະນຸຍາດ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ໃຫ້ເຂົ້າເຖິງຂໍ້ມູນນີ້ຈາກໂທລະສັບຂອງທ່ານໄດ້"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"ການແຈ້ງເຕືອນ"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"ສາມາດອ່ານການແຈ້ງເຕືອນທັງໝົດ, ຮວມທັງຂໍ້ມູນ ເຊັ່ນ: ລາຍຊື່ຜູ້ຕິດຕໍ່, ຂໍ້ຄວາມ ແລະ ຮູບພາບ"</string> + <string name="permission_storage" msgid="6831099350839392343">"ຮູບພາບ ແລະ ມີເດຍ"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"ບໍລິການ Google Play"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> ກຳລັງຮ້ອງຂໍການອະນຸຍາດໃນນາມຂອງ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ເພື່ອສະຕຣີມແອັບລະຫວ່າງອຸປະກອນຂອງທ່ານ"</string> <string name="profile_name_generic" msgid="6851028682723034988">"ອຸປະກອນ"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"ອະນຸຍາດ"</string> <string name="consent_no" msgid="2640796915611404382">"ບໍ່ອະນຸຍາດ"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"ໂອນຍ້າຍການອະນຸຍາດແອັບໄປຫາໂມງຂອງທ່ານ"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"ເພື່ອເຮັດໃຫ້ຕັ້ງຄ່າໂມງຂອງທ່ານໄດ້ງ່າຍຂຶ້ນ, ແອັບທີ່ຕິດຕັ້ງຢູ່ໂມງຂອງທ່ານໃນລະຫວ່າງການຕັ້ງຄ່າຈະໃຊ້ການອະນຸຍາດດຽວກັນກັບໂທລະສັບຂອງທ່ານ.\n\n ການອະນຸຍາດເຫຼົ່ານີ້ອາດຮວມສິດເຂົ້າເຖິງໄມໂຄຣໂຟນ ແລະ ສະຖານທີ່ຂອງທ່ານນຳ."</string> + <string name="consent_back" msgid="2560683030046918882">"ກັບຄືນ"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"ໃຫ້ການອະນຸຍາດແອັບຢູ່ <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> ເປັນການອະນຸຍາດດຽວກັນກັບຢູ່ <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> ບໍ?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>ນີ້ອາດຮວມສິດເຂົ້າເຖິງໄມໂຄຣໂຟນ, ກ້ອງຖ່າຍຮູບ ແລະ ສະຖານທີ່, ຮວມທັງການອະນຸຍາດທີ່ລະອຽດອ່ອນອື່ນໆຢູ່ <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>ທ່ານສາມາດປ່ຽນການອະນຸຍາດເຫຼົ່ານີ້ຕອນໃດກໍໄດ້ໃນການຕັ້ງຄ່າຂອງທ່ານຢູ່ <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-lt/strings.xml b/packages/CompanionDeviceManager/res/values-lt/strings.xml index 5d32fbbf9116..248791da6e5b 100644 --- a/packages/CompanionDeviceManager/res/values-lt/strings.xml +++ b/packages/CompanionDeviceManager/res/values-lt/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Jūsų <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, kurį valdys <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> (pasirinkite)"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ galės sąveikauti su pranešimų funkcija ir pasiekti telefoną, SMS, kontaktus ir kalendorių."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ galės sąveikauti su pranešimų funkcija ir pasiekti telefoną, SMS, kontaktus ir kalendorių."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Leisti <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> perduoti srautu programas?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Leiskite <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> prisijungus suteikti <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> nuotolinę prieigą prie šiame telefone įdiegtų programų."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Leiskite <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> prisijungus suteikti <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> nuotolinę prieigą prie šiame planšetiniame kompiuteryje įdiegtų programų."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Leiskite <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> prisijungus suteikti <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> nuotolinę prieigą prie šiame įrenginyje įdiegtų programų."</string> + <string name="permission_apps" msgid="6142133265286656158">"Programos"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Telefono programų perdavimas srautu"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Leisti <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pasiekti šią informaciją iš jūsų telefono"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Pasl. keliuose įrenginiuose"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"Programa „<xliff:g id="APP_NAME">%1$s</xliff:g>“ prašo leidimo jūsų „<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>“ vardu, kad galėtų pasiekti telefono nuotraukas, mediją ir pranešimus"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Leisti <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pasiekti šią informaciją iš jūsų telefono"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Pranešimai"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Galima skaityti visus pranešimus, įskaitant tokią informaciją kaip kontaktai, pranešimai ir nuotraukos"</string> + <string name="permission_storage" msgid="6831099350839392343">"Nuotraukos ir medija"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"„Google Play“ paslaugos"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"Programa „<xliff:g id="APP_NAME">%1$s</xliff:g>“ prašo leidimo jūsų „<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>“ vardu, kad galėtų srautu perduoti programas iš vieno įrenginio į kitą"</string> <string name="profile_name_generic" msgid="6851028682723034988">"įrenginys"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Leisti"</string> <string name="consent_no" msgid="2640796915611404382">"Neleisti"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Laikrodžio programų perkėlimo leidimai"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Kad būtų lengviau nustatyti laikrodį, jame atliekant sąranką įdiegtoms programoms bus naudojami tie patys leidimai kaip jūsų telefone.\n\n Šie leidimai gali apimti prieigą prie laikrodžio mikrofono ir vietovės."</string> + <string name="consent_back" msgid="2560683030046918882">"Atgal"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Suteikti <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> esančioms programoms tuos pačius leidimus kaip <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> esančioms programoms?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Gali būti įtraukti prieigos prie mikrofono, kameros ir vietovės leidimai ir kiti leidimai pasiekti neskelbtiną informaciją <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> įrenginyje.</p> <p>Šiuos leidimus galite bet kada pakeisti „Nustatymų“ skiltyje <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> įrenginyje.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-lv/strings.xml b/packages/CompanionDeviceManager/res/values-lv/strings.xml index cabfc77bb27c..5e1c16a7fa43 100644 --- a/packages/CompanionDeviceManager/res/values-lv/strings.xml +++ b/packages/CompanionDeviceManager/res/values-lv/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Profila (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>) izvēle, ko pārvaldīt lietotnē <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"Lietotnei <xliff:g id="APP_NAME">%1$s</xliff:g> tiks atļauts mijiedarboties ar jūsu paziņojumiem un piekļūt šādām atļaujām: Tālrunis, Īsziņas, Kontaktpersonas un Kalendārs."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"Lietotnei <xliff:g id="APP_NAME">%1$s</xliff:g> tiks atļauts mijiedarboties ar jūsu paziņojumiem un piekļūt šādām atļaujām: Tālrunis, Īsziņas, Kontaktpersonas un Kalendārs."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Vai atļaujat lietotnei <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> straumēt lietojumprogrammas?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Atļaut lietotnei <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> nodrošināt attālu piekļuvi tālrunim <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>, lai piekļūtu šajā tālrunī instalētajām lietojumprogrammām, kamēr ir izveidots savienojums."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Atļaut lietotnei <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> nodrošināt attālu piekļuvi planšetdatoram <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>, lai piekļūtu šajā planšetdatorā instalētajām lietojumprogrammām, kamēr ir izveidots savienojums."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Atļaut lietotnei <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> nodrošināt attālu piekļuvi ierīcei <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>, lai piekļūtu šajā ierīcē instalētajām lietojumprogrammām, kamēr ir izveidots savienojums."</string> + <string name="permission_apps" msgid="6142133265286656158">"Lietotnes"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Var straumēt jūsu tālruņa lietotnes"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Atļaut lietotnei <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> piekļūt šai informācijai no jūsu tālruņa"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Vairāku ierīču pakalpojumi"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> pieprasa atļauju piekļūt jūsu tālruņa fotoattēliem, multivides saturam un paziņojumiem šīs ierīces vārdā: <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Atļaut lietotnei <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> piekļūt šai informācijai no jūsu tālruņa"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Paziņojumi"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Var lasīt visus paziņojumus, tostarp tādu informāciju kā kontaktpersonas, ziņojumi un fotoattēli."</string> + <string name="permission_storage" msgid="6831099350839392343">"Fotoattēli un multivides faili"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play pakalpojumi"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> pieprasa atļauju straumēt lietotnes starp jūsu ierīcēm šīs ierīces vārdā: <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="profile_name_generic" msgid="6851028682723034988">"ierīce"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Atļaut"</string> <string name="consent_no" msgid="2640796915611404382">"Neatļaut"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Lietotņu atļauju pārsūtīšana uz pulksteni"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Lai atvieglotu pulksteņa iestatīšanu, iestatīšanas laikā pulkstenī instalētās lietotnes saņems tādas pašas atļaujas, kādas tām ir tālrunī.\n\n Tostarp lietotnes var saņemt atļauju piekļūt pulksteņa mikrofonam un atrašanās vietai."</string> + <string name="consent_back" msgid="2560683030046918882">"Atpakaļ"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Vai lietotnēm ierīcē <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> piešķirt tādas pašas atļaujas kā ierīcē <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Tās var būt mikrofona, kameras, atrašanās vietas piekļuves atļaujas un citas sensitīvas atļaujas ierīcē <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Atļaujas jebkurā brīdī varat mainīt ierīces <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p> iestatījumos."</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-mk/strings.xml b/packages/CompanionDeviceManager/res/values-mk/strings.xml index b4531b5c864e..d0b8bbe2778c 100644 --- a/packages/CompanionDeviceManager/res/values-mk/strings.xml +++ b/packages/CompanionDeviceManager/res/values-mk/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Изберете <xliff:g id="PROFILE_NAME">%1$s</xliff:g> со којшто ќе управува <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ќе може да остварува интеракција со известувањата и да пристапува до дозволите за телефонот, SMS, контактите и календарот."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ќе може да остварува интеракција со известувањата и да пристапува до дозволите за телефонот, SMS, контактите и календарот."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Да се дозволи <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да стримува апликации?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Дозволете <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да обезбеди далечински пристап на <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> за да пристапува до апликации инсталирани на телефонов кога ќе се поврзе."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Дозволете <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да обезбеди далечински пристап на <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> за да пристапува до апликации инсталирани на таблетов кога ќе се поврзе."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Дозволете <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да обезбеди далечински пристап на <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> за да пристапува до апликации инсталирани на уредов кога ќе се поврзе."</string> + <string name="permission_apps" msgid="6142133265286656158">"Апликации"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Стримувајте ги апликациите на телефонот"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Овозможете <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да пристапува до овие податоци на телефонот"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Повеќенаменски услуги"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> бара дозвола во име на вашиот <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> за да пристапува до фотографиите, аудиовизуелните содржини и известувањата на телефонот"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Овозможете <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да пристапува до овие податоци на телефонот"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Известувања"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"може да ги чита сите известувања, вклучително и податоци како контакти, пораки и фотографии"</string> + <string name="permission_storage" msgid="6831099350839392343">"Аудиовизуелни содржини"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Услуги на Google Play"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> бара дозвола во име на вашиот <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> за да стримува апликации помеѓу вашите уреди"</string> <string name="profile_name_generic" msgid="6851028682723034988">"уред"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Дозволи"</string> <string name="consent_no" msgid="2640796915611404382">"Не дозволувај"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Префрлете ги дозволите за апликациите на вашиот часовник"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"За полесно поставувањето на часовникот, апликациите инсталирани на часовникот при поставувањето ќе ги користат истите дозволи како на телефонот.\n\n Овие дозволи може да опфаќаат пристап до микрофонот и локацијата на часовникот."</string> + <string name="consent_back" msgid="2560683030046918882">"Назад"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Дасе дадат исти дозволи на апликациите на <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> како на <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Ова може да вклучува пристап до микрофон, камера и локација и други чувствителни дозволи на <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Може да ги промените дозволиве во секое време во вашите „Поставки“ на <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-ml/strings.xml b/packages/CompanionDeviceManager/res/values-ml/strings.xml index 85952ca65fce..5f11bc21496d 100644 --- a/packages/CompanionDeviceManager/res/values-ml/strings.xml +++ b/packages/CompanionDeviceManager/res/values-ml/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> ഉപയോഗിച്ച് മാനേജ് ചെയ്യുന്നതിന് ഒരു <xliff:g id="PROFILE_NAME">%1$s</xliff:g> തിരഞ്ഞെടുക്കുക"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"നിങ്ങളുടെ അറിയിപ്പുകളുമായി സംവദിക്കാനും നിങ്ങളുടെ ഫോൺ, SMS, കോൺടാക്റ്റുകൾ, കലണ്ടർ അനുമതികൾ എന്നിവ ആക്സസ് ചെയ്യാനും <xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിനെ അനുവദിക്കും."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"നിങ്ങളുടെ അറിയിപ്പുകളുമായി സംവദിക്കാനും നിങ്ങളുടെ ഫോൺ, SMS, കോൺടാക്റ്റുകൾ, കലണ്ടർ അനുമതികൾ എന്നിവ ആക്സസ് ചെയ്യാനും <xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിനെ അനുവദിക്കും."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"ആപ്പുകൾ സ്ട്രീം ചെയ്യാൻ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> എന്നതിനെ അനുവദിക്കണോ?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"കണക്റ്റ് ചെയ്യുമ്പോൾ, ഈ ഫോണിൽ ഇൻസ്റ്റാൾ ചെയ്തിട്ടുള്ള ആപ്പുകൾ ആക്സസ് ചെയ്യാനുള്ള റിമോട്ട് ആക്സസ് <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> എന്നതിന് നൽകാൻ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> എന്നതിനെ അനുവദിക്കുക."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"കണക്റ്റ് ചെയ്യുമ്പോൾ, ഈ ടാബ്ലെറ്റിൽ ഇൻസ്റ്റാൾ ചെയ്തിട്ടുള്ള ആപ്പുകൾ ആക്സസ് ചെയ്യാനുള്ള റിമോട്ട് ആക്സസ് <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> എന്നതിന് നൽകാൻ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> എന്നതിനെ അനുവദിക്കുക."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"കണക്റ്റ് ചെയ്യുമ്പോൾ, ഈ ഉപകരണത്തിൽ ഇൻസ്റ്റാൾ ചെയ്തിട്ടുള്ള ആപ്പുകൾ ആക്സസ് ചെയ്യാനുള്ള റിമോട്ട് ആക്സസ് <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> എന്നതിന് നൽകാൻ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> എന്നതിനെ അനുവദിക്കുക."</string> + <string name="permission_apps" msgid="6142133265286656158">"ആപ്പുകൾ"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"നിങ്ങളുടെ ഫോണിലെ ആപ്പുകൾ സ്ട്രീം ചെയ്യാൻ"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"നിങ്ങളുടെ ഫോണിൽ നിന്ന് ഈ വിവരങ്ങൾ ആക്സസ് ചെയ്യാൻ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ആപ്പിനെ അനുവദിക്കുക"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"ക്രോസ്-ഉപകരണ സേവനങ്ങൾ"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"നിങ്ങളുടെ ഫോണിലെ ഫോട്ടോകൾ, മീഡിയ, അറിയിപ്പുകൾ എന്നിവ ആക്സസ് ചെയ്യാൻ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ഉപകരണത്തിനു വേണ്ടി <xliff:g id="APP_NAME">%1$s</xliff:g> അനുമതി അഭ്യർത്ഥിക്കുന്നു."</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"നിങ്ങളുടെ ഫോണിൽ നിന്ന് ഈ വിവരങ്ങൾ ആക്സസ് ചെയ്യാൻ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ആപ്പിനെ അനുവദിക്കുക"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"അറിയിപ്പുകൾ"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"കോൺടാക്റ്റുകൾ, സന്ദേശങ്ങൾ, ഫോട്ടോകൾ മുതലായ വിവരങ്ങൾ ഉൾപ്പെടെയുള്ള എല്ലാ അറിയിപ്പുകളും വായിക്കാനാകും"</string> + <string name="permission_storage" msgid="6831099350839392343">"ഫോട്ടോകളും മീഡിയയും"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play സേവനങ്ങൾ"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"നിങ്ങളുടെ ഉപകരണങ്ങളിൽ ഒന്നിൽ നിന്ന് അടുത്തതിലേക്ക് ആപ്പുകൾ സ്ട്രീം ചെയ്യാൻ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ഉപകരണത്തിനു വേണ്ടി <xliff:g id="APP_NAME">%1$s</xliff:g> അനുമതി അഭ്യർത്ഥിക്കുന്നു."</string> <string name="profile_name_generic" msgid="6851028682723034988">"ഉപകരണം"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"അനുവദിക്കുക"</string> <string name="consent_no" msgid="2640796915611404382">"അനുവദിക്കരുത്"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"നിങ്ങളുടെ വാച്ചിലേക്ക് ആപ്പ് അനുമതികൾ കൈമാറുക"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"നിങ്ങളുടെ വാച്ച് സജ്ജീകരിക്കുന്നത് എളുപ്പമാക്കാൻ, സജ്ജീകരിക്കുമ്പോൾ ഫോണിലുള്ള അതേ അനുമതികൾ നിങ്ങളുടെ വാച്ചിൽ ഇൻസ്റ്റാൾ ചെയ്തിട്ടുള്ള ആപ്പുകൾ ഉപയോഗിക്കും.\n\n ഈ അനുമതികളിൽ നിങ്ങളുടെ വാച്ചിന്റെ മൈക്രോഫോണിലേക്കും ലോക്കേഷനിലേക്കുമുള്ള ആക്സസ് ഉൾപ്പെട്ടേക്കാം."</string> + <string name="consent_back" msgid="2560683030046918882">"മടങ്ങുക"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> എന്നതിലെ അതേ അനുമതികൾ <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> എന്നതിലെ ആപ്പുകൾക്ക് നൽകണോ?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p><strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> എന്നതിലെ മൈക്രോഫോൺ, ക്യാമറ, ലൊക്കേഷൻ ആക്സസ്, സെൻസിറ്റീവ് വിവരങ്ങൾക്കുള്ള മറ്റ് അനുമതികൾ എന്നിവയും ഇതിൽ ഉൾപ്പെട്ടേക്കാം<p>നിങ്ങൾക്ക് <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p> എന്നതിലെ ക്രമീകരണത്തിൽ ഏതുസമയത്തും ഈ അനുമതികൾ മാറ്റാം."</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-mn/strings.xml b/packages/CompanionDeviceManager/res/values-mn/strings.xml index c0d589d0aca7..58e138584fd4 100644 --- a/packages/CompanionDeviceManager/res/values-mn/strings.xml +++ b/packages/CompanionDeviceManager/res/values-mn/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>-н удирдах<xliff:g id="PROFILE_NAME">%1$s</xliff:g>-г сонгоно уу"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g>-д таны мэдэгдлүүдтэй харилцаж, таны Утас, SMS, Харилцагчид болон Календарийн зөвшөөрөлд хандахыг зөвшөөрнө."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g>-д таны мэдэгдлүүдтэй харилцаж, таны Утас, SMS, Харилцагчид болон Календарийн зөвшөөрөлд хандахыг зөвшөөрнө."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-д аппуудыг дамжуулахыг зөвшөөрөх үү?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-д <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>-г холбогдсон үед энэ утсанд суулгасан аппуудад хандахын тулд алсын хандалт өгөхийг зөвшөөрнө үү."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-д <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>-г холбогдсон үед энэ таблетад суулгасан аппуудад хандахын тулд алсын хандалт өгөхийг зөвшөөрнө үү."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-д <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>-г холбогдсон үед энэ төхөөрөмжид суулгасан аппуудад хандахын тулд алсын хандалт өгөхийг зөвшөөрнө үү."</string> + <string name="permission_apps" msgid="6142133265286656158">"Аппууд"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Таны утасны аппуудыг дамжуулах"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-д таны утаснаас энэ мэдээлэлд хандахыг зөвшөөрнө үү"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Төхөөрөмж хоорондын үйлчилгээ"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> нь таны <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-н өмнөөс утасны зураг, медиа болон мэдэгдэлд хандахын тулд зөвшөөрөл хүсэж байна"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-д таны утаснаас энэ мэдээлэлд хандахыг зөвшөөрнө үү"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Мэдэгдэл"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Харилцагчид, мессеж болон зураг зэрэг мэдээллийг оруулаад бүх мэдэгдлийг унших боломжтой"</string> + <string name="permission_storage" msgid="6831099350839392343">"Зураг болон медиа"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play үйлчилгээ"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> нь таны <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-н өмнөөс төхөөрөмж хооронд апп дамжуулахын тулд зөвшөөрөл хүсэж байна"</string> <string name="profile_name_generic" msgid="6851028682723034988">"төхөөрөмж"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Зөвшөөрөх"</string> <string name="consent_no" msgid="2640796915611404382">"Бүү зөвшөөр"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Цагандаа аппын зөвшөөрлийг шилжүүлэх"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Таны цагийг тохируулахад илүү хялбар болгохын тулд тохируулгын үеэр таны цаган дээр суулгасан аппууд нь утастай тань ижил зөвшөөрлийг ашиглана.\n\n Эдгээр зөвшөөрөлд таны цагийн микрофон болон байршлын хандалт зэрэг багтаж магадгүй."</string> + <string name="consent_back" msgid="2560683030046918882">"Буцах"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> дээрх аппуудад <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> дээрхтэй адил зөвшөөрөл өгөх үү?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Үүнд Микрофон, Камер болон Байршлын хандалт болон <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> дээрх бусад эмзэг зөвшөөрөл багтаж болно.</p> <p>Та эдгээр зөвшөөрлийг <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> дээрх Тохиргоо хэсэгтээ хүссэн үедээ өөрчлөх боломжтой.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-mr/strings.xml b/packages/CompanionDeviceManager/res/values-mr/strings.xml index 0ce6ab712eb0..1c38932daead 100644 --- a/packages/CompanionDeviceManager/res/values-mr/strings.xml +++ b/packages/CompanionDeviceManager/res/values-mr/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> द्वारे व्यवस्थापित करण्यासाठी <xliff:g id="PROFILE_NAME">%1$s</xliff:g> निवडा"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ला तुमच्या सूचनांशी संवाद साधण्याची आणि तुमचा फोन, एसएमएस, संपर्क आणि Calendar च्या परवानग्या अॅक्सेस करण्याची अनुमती मिळेल."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ला तुमच्या सूचनांशी संवाद साधण्याची आणि तुमचा फोन, एसएमएस, संपर्क आणि Calendar च्या परवानग्या अॅक्सेस करण्याची अनुमती मिळेल."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ला अॅप्लिकेशन स्ट्रीम करण्याची अनुमती द्यायची आहे का?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"कनेक्ट केलेले असताना या फोनवरील अॅप्लिकेशन अॅक्सेस करता यावीत यासाठी <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ला <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> चा रिमोट अॅक्सेस द्या."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"कनेक्ट केलेले असताना या टॅबलेटवरील अॅप्लिकेशन अॅक्सेस करता यावीत यासाठी <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ला <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> चा रिमोट अॅक्सेस द्या."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"कनेक्ट केलेले असताना या डिव्हाइसवरील अॅप्लिकेशन अॅक्सेस करता यावीत यासाठी <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ला <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> चा रिमोट अॅक्सेस द्या."</string> + <string name="permission_apps" msgid="6142133265286656158">"ॲप्स"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"फोनवरील ॲप्स स्ट्रीम करा"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ला ही माहिती तुमच्या फोनवरून अॅक्सेस करण्यासाठी अनुमती द्या"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"क्रॉस-डिव्हाइस सेवा"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"तुमच्या फोनमधील फोटो, मीडिया आणि सूचना ॲक्सेस करण्यासाठी <xliff:g id="APP_NAME">%1$s</xliff:g> हे तुमच्या <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> च्या वतीने परवानगीची विनंती करत आहे"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ला ही माहिती तुमच्या फोनवरून अॅक्सेस करण्यासाठी अनुमती द्या"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"सूचना"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"संपर्क, मेसेज आणि फोटो यांसारख्या माहितीचा समावेश असलेल्या सर्व सूचना वाचू शकते"</string> + <string name="permission_storage" msgid="6831099350839392343">"फोटो आणि मीडिया"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play सेवा"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"तुमच्या डिव्हाइसदरम्यान ॲप्स स्ट्रीम करण्यासाठी <xliff:g id="APP_NAME">%1$s</xliff:g> हे तुमच्या <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> च्या वतीने परवानगीची विनंती करत आहे"</string> <string name="profile_name_generic" msgid="6851028682723034988">"डिव्हाइस"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"अनुमती द्या"</string> <string name="consent_no" msgid="2640796915611404382">"अनुमती देऊ नका"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"अॅप परवानग्या तुमच्या वॉचवर ट्रान्सफर करा"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"तुमचे वॉच सेट करणे आणखी सोपे करण्यासाठी, सेटअपदरम्यान तुमच्या वॉचवर इंस्टॉल केलेली ॲप्स ही तुमच्या फोनप्रमाणेच परवानग्या वापरतील.\n\n या परवानग्यांमध्ये तुमच्या वॉचचा मायक्रोफोन आणि स्थानाच्या अॅक्सेसचा समावेश असू शकतो."</string> + <string name="consent_back" msgid="2560683030046918882">"मागे जा"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> वरील अॅप्सना <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> प्रमाणेच परवानग्या द्यायच्या आहेत का?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>यामध्ये <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g><strong> वरील मायक्रोफोन, कॅमेरा आणि स्थान अॅक्सेस व इतर संवेदनशील परवानग्यांचा समावेश असू शकतो </strong>.</p> <p>तुम्ही <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> वर तुमच्या सेटिंग्ज मध्ये या परवानग्या कधीही बदलू शकता</strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-ms/strings.xml b/packages/CompanionDeviceManager/res/values-ms/strings.xml index 2ca812889342..a76f5e9303b3 100644 --- a/packages/CompanionDeviceManager/res/values-ms/strings.xml +++ b/packages/CompanionDeviceManager/res/values-ms/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Pilih <xliff:g id="PROFILE_NAME">%1$s</xliff:g> untuk diurus oleh <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> akan dibenarkan berinteraksi dengan pemberitahuan anda dan mengakses kebenaran Telefon, SMS, Kenalan dan Kalendar anda."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> akan dibenarkan berinteraksi dengan pemberitahuan anda dan mengakses kebenaran Telefon, SMS, Kenalan dan Kalendar anda."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Benarkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> menstrim aplikasi?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Membenarkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> memberi akses jauh kepada <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> untuk mengakses aplikasi yang dipasang pada telefon ini apabila disambungkan."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Membenarkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> memberi akses jauh kepada <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> untuk mengakses aplikasi yang dipasang pada tablet ini apabila disambungkan."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Membenarkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> memberi akses jauh kepada <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> untuk mengakses aplikasi yang dipasang pada peranti ini apabila disambungkan."</string> + <string name="permission_apps" msgid="6142133265286656158">"Apl"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Strim apl telefon anda"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Benarkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> mengakses maklumat ini daripada telefon anda"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Perkhidmatan silang peranti"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> sedang meminta kebenaran bagi pihak <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> anda untuk mengakses foto, media dan pemberitahuan telefon anda"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Benarkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> untuk mengakses maklumat ini daripada telefon anda"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Pemberitahuan"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Boleh membaca semua pemberitahuan, termasuk maklumat seperti kenalan, mesej dan foto"</string> + <string name="permission_storage" msgid="6831099350839392343">"Foto dan media"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Perkhidmatan Google Play"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> sedang meminta kebenaran bagi pihak <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> anda untuk menstrim apl antara peranti anda"</string> <string name="profile_name_generic" msgid="6851028682723034988">"peranti"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Benarkan"</string> <string name="consent_no" msgid="2640796915611404382">"Jangan benarkan"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Pindahkan kebenaran apl pada jam tangan anda"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Untuk memudahkan penyediaan jam tangan anda, apl yang dipasang pada jam tangan anda semasa persediaan akan menggunakan kebenaran yang sama seperti telefon anda.\n\n Kebenaran ini mungkin termasuk akses kepada mikrofon dan lokasi jam tangan anda."</string> + <string name="consent_back" msgid="2560683030046918882">"Kembali"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Berikan apl <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> kebenaran yang sama seperti pada <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Ini mungkin termasuk akses Mikrofon, Kamera dan Lokasi serta kebenaran sensitif lain pada <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Anda boleh menukar kebenaran ini pada bila-bila masa dalam Tetapan anda pada <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-my/strings.xml b/packages/CompanionDeviceManager/res/values-my/strings.xml index 1fb20bf2449e..39502051babf 100644 --- a/packages/CompanionDeviceManager/res/values-my/strings.xml +++ b/packages/CompanionDeviceManager/res/values-my/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> က စီမံခန့်ခွဲရန် <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ကို ရွေးချယ်ပါ"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"သင်၏ ‘ဖုန်း’၊ ‘SMS စာတိုစနစ်’၊ ‘အဆက်အသွယ်များ’ နှင့် ‘ပြက္ခဒိန်’ ခွင့်ပြုချက်များကို သုံးရန်နှင့် အကြောင်းကြားချက်များကို ပြန်လှန်တုံ့ပြန်ရန် <xliff:g id="APP_NAME">%1$s</xliff:g> အား ခွင့်ပြုပါမည်။"</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"သင်၏ ‘ဖုန်း’၊ ‘SMS စာတိုစနစ်’၊ ‘အဆက်အသွယ်များ’ နှင့် ‘ပြက္ခဒိန်’ ခွင့်ပြုချက်များကို သုံးရန်နှင့် အကြောင်းကြားချက်များကို ပြန်လှန်တုံ့ပြန်ရန် <xliff:g id="APP_NAME">%1$s</xliff:g> အား ခွင့်ပြုပါမည်။"</string> - <string name="title_app_streaming" msgid="4459136600249308574">"အပလီကေးရှင်းများကို တိုက်ရိုက်လွှင့်ရန် <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ကိုခွင့်ပြုမလား။"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"ချိတ်ဆက်ထားသည့်အခါ ဤဖုန်းတွင် ထည့်သွင်းထားသော အပလီကေးရှင်းများကို သုံးခွင့်ရရန်အတွက် <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ကိုအဝေးမှ သုံးခွင့်ပေးနိုင်ရန် <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> အားခွင့်ပြုပါ။"</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"ချိတ်ဆက်ထားသည့်အခါ ဤတက်ဘလက်တွင် ထည့်သွင်းထားသော အပလီကေးရှင်းများကို သုံးခွင့်ရရန်အတွက် <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ကိုအဝေးမှ သုံးခွင့်ပေးနိုင်ရန် <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> အားခွင့်ပြုပါ။"</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"ချိတ်ဆက်ထားသည့်အခါ ဤစက်တွင် ထည့်သွင်းထားသော အပလီကေးရှင်းများကို သုံးခွင့်ရရန်အတွက် <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ကိုအဝေးမှ သုံးခွင့်ပေးနိုင်ရန် <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> အားခွင့်ပြုပါ။"</string> + <string name="permission_apps" msgid="6142133265286656158">"အက်ပ်များ"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"သင့်ဖုန်းရှိအက်ပ်များကို တိုက်ရိုက်လွှင့်နိုင်သည်"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ကို သင့်ဖုန်းမှ ဤအချက်အလက် သုံးခွင့်ပြုမည်"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"စက်များကြားသုံး ဝန်ဆောင်မှုများ"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> သည် သင့်ဖုန်း၏ ဓာတ်ပုံ၊ မီဒီယာနှင့် အကြောင်းကြားချက်များသုံးရန် သင်၏ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ကိုယ်စား ခွင့်ပြုချက်တောင်းနေသည်"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ကို သင့်ဖုန်းမှ ဤအချက်အလက် သုံးခွင့်ပြုမည်"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"အကြောင်းကြားချက်များ"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"အဆက်အသွယ်၊ မက်ဆေ့ဂျ်နှင့် ဓာတ်ပုံကဲ့သို့ အချက်အလက်များအပါအဝင် အကြောင်းကြားချက်အားလုံးကို ဖတ်နိုင်သည်"</string> + <string name="permission_storage" msgid="6831099350839392343">"ဓာတ်ပုံနှင့် မီဒီယာများ"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play ဝန်ဆောင်မှုများ"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> သည် သင်၏စက်များအကြား အက်ပ်များတိုက်ရိုက်လွှင့်ရန် သင်၏ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ကိုယ်စား ခွင့်ပြုချက်တောင်းနေသည်"</string> <string name="profile_name_generic" msgid="6851028682723034988">"စက်"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"ခွင့်ပြုရန်"</string> <string name="consent_no" msgid="2640796915611404382">"ခွင့်မပြုပါ"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"သင်၏နာရီသို့ အက်ပ်ခွင့်ပြုချက်များ လွှဲပြောင်းရန်"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"သင်၏နာရီ စနစ်ထည့်သွင်းရာတွင် ပိုလွယ်ကူစေရန် စနစ်ထည့်သွင်းနေစဉ်အတွင်း နာရီတွင်ထည့်သွင်းသော အက်ပ်များသည် သင့်ဖုန်းနှင့် အလားတူခွင့်ပြုချက်များကို သုံးပါမည်။\n\n ဤခွင့်ပြုချက်များတွင် သင့်နာရီ၏ မိုက်ခရိုဖုန်းနှင့် တည်နေရာတို့ကို သုံးခွင့် ပါဝင်နိုင်သည်။"</string> + <string name="consent_back" msgid="2560683030046918882">"နောက်သို့"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"အက်ပ်များကို <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> တွင်ပေးထားသည့် ခွင့်ပြုချက်များအတိုင်း <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> တွင် ပေးမလား။"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>၎င်းတွင် မိုက်ခရိုဖုန်း၊ ကင်မရာ၊ တည်နေရာ အသုံးပြုခွင့်အပြင် <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>ပေါ်ရှိ အခြား သတိထားရမည့် ခွင့်ပြုချက်များ ပါဝင်နိုင်သည်။</p> <p>ဤခွင့်ပြုချက်များကို <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>ပေါ်ရှိ သင်၏ဆက်တင်များတွင် အချိန်မရွေးပြောင်းနိုင်သည်။</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-nb/strings.xml b/packages/CompanionDeviceManager/res/values-nb/strings.xml index aa73f5dff065..9bbacb647451 100644 --- a/packages/CompanionDeviceManager/res/values-nb/strings.xml +++ b/packages/CompanionDeviceManager/res/values-nb/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Velg <xliff:g id="PROFILE_NAME">%1$s</xliff:g> som skal administreres av <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> får tillatelse til å samhandle med varslene dine og får tilgang til Telefon, SMS, kontakter og Kalender."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> får tillatelse til å samhandle med varslene dine og får tilgang til Telefon, SMS, kontakter og Kalender."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Vil du gi <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tillatelse til å strømme apper?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Tillat at <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> gir <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ekstern tilgang til apper som er installert på denne telefonen, når den er koblet til internett."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Tillat at <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> gir <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ekstern tilgang til apper som er installert på dette nettbrettet, når det er koblet til internett."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Tillat at <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> gir <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ekstern tilgang til apper som er installert på denne enheten, når den er koblet til internett."</string> + <string name="permission_apps" msgid="6142133265286656158">"Apper"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Strøm appene på telefonen"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Gi <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tilgang til denne informasjonen fra telefonen din"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Tjenester på flere enheter"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> ber om tillatelse på vegne av <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> for å få tilgang til bilder, medier og varsler på telefonen din"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Gi <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tilgang til denne informasjonen fra telefonen din"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Varsler"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Kan lese alle varsler, inkludert informasjon som kontakter, meldinger og bilder"</string> + <string name="permission_storage" msgid="6831099350839392343">"Bilder og medier"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play-tjenester"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> ber om tillatelse på vegne av <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> for å strømme apper mellom enhetene dine"</string> <string name="profile_name_generic" msgid="6851028682723034988">"enhet"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Tillat"</string> <string name="consent_no" msgid="2640796915611404382">"Ikke tillat"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Overfør apptillatelser til klokken din"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"For å gjøre det enklere å konfigurere klokken din bruker apper som installeres på klokken under konfigureringen, samme tillatelser som på telefonen.\n\n Disse tillatelsene kan inkludere tilgang til mikrofonen på klokken og posisjon."</string> + <string name="consent_back" msgid="2560683030046918882">"Tilbake"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Vil du gi apper på <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> de samme tillatelsene som på <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Dette kan inkludere tilgang til mikrofon, kamera og posisjon samt andre sensitive tillatelser på <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Du kan når som helst endre disse tillatelsene i innstillingene på <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-ne/strings.xml b/packages/CompanionDeviceManager/res/values-ne/strings.xml index 3ba75eb31aad..cec076e7a5d8 100644 --- a/packages/CompanionDeviceManager/res/values-ne/strings.xml +++ b/packages/CompanionDeviceManager/res/values-ne/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"आफूले <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> प्रयोग गरी व्यवस्थापन गर्न चाहेको <xliff:g id="PROFILE_NAME">%1$s</xliff:g> चयन गर्नुहोस्"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> लाई तपाईंका सूचना हेर्ने र फोन, SMS, कन्ट्याक्ट तथा पात्रोसम्बन्धी अनुमतिहरू हेर्ने तथा प्रयोग गर्ने अनुमति दिइने छ।"</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> लाई तपाईंका सूचना हेर्ने र फोन, SMS, कन्ट्याक्ट तथा पात्रोसम्बन्धी अनुमतिहरू हेर्ने तथा प्रयोग गर्ने अनुमति दिइने छ।"</string> - <string name="title_app_streaming" msgid="4459136600249308574">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> लाई एपहरू स्ट्रिम गर्ने अनुमति दिने हो?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"यो डिभाइस इन्टरनेटमा कनेक्ट भएका बेला, <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>लाई <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> लाई यो फोनमा इन्स्टल गरिएका एप टाढैबाट प्रयोग गर्ने अनुमति दिन दिनुहोस्।"</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"यो डिभाइस इन्टरनेटमा कनेक्ट भएका बेला, <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>लाई <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> लाई यो ट्याब्लेटमा इन्स्टल गरिएका एप टाढैबाट प्रयोग गर्ने अनुमति दिन दिनुहोस्।"</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"यो डिभाइस इन्टरनेटमा कनेक्ट भएका बेला, <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> लाई <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> लाई यो डिभाइसमा इन्स्टल गरिएका एप टाढैबाट प्रयोग गर्ने अनुमति दिन दिनुहोस्।"</string> + <string name="permission_apps" msgid="6142133265286656158">"एपहरू"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"आफ्नो फोनका एपहरू प्रयोग गर्नुहोस्"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> लाई तपाईंको फोनमा भएको यो जानकारी हेर्ने तथा प्रयोग गर्ने अनुमति दिनुहोस्"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"क्रस-डिभाइस सेवाहरू"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> तपाईंको डिभाइस <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> को तर्फबाट तपाईंको फोनमा भएका फोटो, मिडिया र सूचनाहरू हेर्ने तथा प्रयोग गर्ने अनुमति माग्दै छ"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> लाई तपाईंको फोनमा भएको यो जानकारी हेर्ने तथा प्रयोग गर्ने अनुमति दिनुहोस्"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"सूचनाहरू"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"कन्ट्याक्ट, म्यासेज र फोटोलगायतका जानकारीसहित सबै सूचनाहरू पढ्न सक्छ"</string> + <string name="permission_storage" msgid="6831099350839392343">"फोटो र मिडिया"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play services"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> तपाईंको डिभाइस <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> को तर्फबाट तपाईंका कुनै एउटा डिभाइसबाट अर्को डिभाइसमा एप स्ट्रिम गर्ने अनुमति माग्दै छ"</string> <string name="profile_name_generic" msgid="6851028682723034988">"यन्त्र"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"अनुमति दिनुहोस्"</string> <string name="consent_no" msgid="2640796915611404382">"अनुमति नदिनुहोस्"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"एपलाई दिइएका अनुमति घडीमा ट्रान्स्फर गर्नुहोस्"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"तपाईंको घडी सेटअप गर्ने कार्य सजिलो बनाउनका लागि सेटअप गर्ने क्रममा तपाईंको घडीमा इन्स्टल गरिएका एपहरूले पनि तपाईंको फोनमा दिइएको जस्तै अनुमति प्रयोग गर्ने छन्।\n\n यी अनुमतिमा तपाईंको घडीको माइक्रोफोन र लोकेसन प्रयोग गर्ने जस्ता अनुमति पर्न सक्छन्।"</string> + <string name="consent_back" msgid="2560683030046918882">"पछाडि"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> मा भएका एपहरूलाई पनि <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> मा दिइएकै अनुमति दिने हो?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>यसअन्तर्गत <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> का माइक्रोफोन, क्यामेरा र लोकेसन प्रयोग गर्ने अनुमतिका तथा अन्य संवेदनशील अनुमति समावेश हुन्छन्।</p> <p>तपाईं <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> का सेटिङमा गई जुनसुकै बेला यी अनुमति परिवर्तन गर्न सक्नुहुन्छ।</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-nl/strings.xml b/packages/CompanionDeviceManager/res/values-nl/strings.xml index bc09a58afee1..1cd307a4165a 100644 --- a/packages/CompanionDeviceManager/res/values-nl/strings.xml +++ b/packages/CompanionDeviceManager/res/values-nl/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Een <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kiezen om te beheren met <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> kan interactie hebben met je meldingen en toegang krijgen tot je rechten voor telefoon, sms, contacten en agenda."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> kan interactie hebben met je meldingen en toegang krijgen tot je rechten voor telefoon, sms, contacten en agenda."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Toestaan dat <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> apps streamt?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Toestaan dat <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> als er verbinding is <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> externe toegang geeft tot apps die zijn geïnstalleerd op deze telefoon."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Toestaan dat <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> als er verbinding is <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> externe toegang geeft tot apps die zijn geïnstalleerd op deze tablet."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Toestaan dat <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> als er verbinding is <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> externe toegang geeft tot apps die zijn geïnstalleerd op dit apparaat."</string> + <string name="permission_apps" msgid="6142133265286656158">"Apps"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"De apps van je telefoon streamen"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> toegang geven tot deze informatie op je telefoon"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device-services"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> vraagt namens jouw <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> toegang tot de foto\'s, media en meldingen van je telefoon"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> toegang geven tot deze informatie op je telefoon"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Meldingen"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Kan alle meldingen lezen, waaronder informatie zoals contacten, berichten en foto\'s"</string> + <string name="permission_storage" msgid="6831099350839392343">"Foto\'s en media"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play-services"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> vraagt namens jouw <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> toestemming om apps te streamen tussen je apparaten"</string> <string name="profile_name_generic" msgid="6851028682723034988">"apparaat"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Toestaan"</string> <string name="consent_no" msgid="2640796915611404382">"Niet toestaan"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"App-rechten overzetten naar je horloge"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"We willen het makkelijker voor je maken om je horloge in te stellen. Daarom gebruiken apps die tijdens het instellen worden geïnstalleerd op je horloge, dezelfde rechten als op je telefoon.\n\n Deze rechten kunnen toegang tot de microfoon en locatie van je horloge omvatten."</string> + <string name="consent_back" msgid="2560683030046918882">"Terug"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Apps op <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong&gt dezelfde rechten geven als op <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Dit kan toegang tot de microfoon, camera en je locatie en andere gevoelige rechten op je <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> omvatten.</p> <p>Je kunt deze rechten op elk moment wijzigen in je Instellingen op de <xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-or/strings.xml b/packages/CompanionDeviceManager/res/values-or/strings.xml index 92d0a5ef5f1d..e4b071c0b898 100644 --- a/packages/CompanionDeviceManager/res/values-or/strings.xml +++ b/packages/CompanionDeviceManager/res/values-or/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> ଦ୍ୱାରା ପରିଚାଳିତ ହେବା ପାଇଁ ଏକ <xliff:g id="PROFILE_NAME">%1$s</xliff:g>କୁ ବାଛନ୍ତୁ"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"ଆପଣଙ୍କ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ସହ ଇଣ୍ଟରାକ୍ଟ କରିବା ଏବଂ ଆପଣଙ୍କ ଫୋନ, SMS, ଯୋଗାଯୋଗ ଓ କ୍ୟାଲେଣ୍ଡର ଅନୁମତିଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିବା ପାଇଁ <xliff:g id="APP_NAME">%1$s</xliff:g>କୁ ଅନୁମତି ଦିଆଯିବ।"</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"ଆପଣଙ୍କ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ସହ ଇଣ୍ଟରାକ୍ଟ କରିବା ଏବଂ ଆପଣଙ୍କ ଫୋନ, SMS, ଯୋଗାଯୋଗ ଓ କ୍ୟାଲେଣ୍ଡର ଅନୁମତିଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିବା ପାଇଁ <xliff:g id="APP_NAME">%1$s</xliff:g>କୁ ଅନୁମତି ଦିଆଯିବ।"</string> - <string name="title_app_streaming" msgid="4459136600249308574">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>କୁ ଆପ୍ଲିକେସନଗୁଡ଼ିକ ଷ୍ଟ୍ରିମ କରିବା ପାଇଁ ଅନୁମତି ଦେବେ କି?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>କୁ, ଏହି ଫୋନଟି ସଂଯୁକ୍ତ ହୋଇଥିବା ବେଳେ ଏଥିରେ ଇନଷ୍ଟଲ କରାଯାଇଥିବା ଆପ୍ଲିକେସନଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିବା ପାଇଁ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>କୁ ରିମୋଟ ଆକ୍ସେସ ପ୍ରଦାନ କରିବାକୁ ଦିଅନ୍ତୁ।"</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>କୁ, ଏହି ଟାବଲେଟଟି ସଂଯୁକ୍ତ ହୋଇଥିବା ବେଳେ ଏଥିରେ ଇନଷ୍ଟଲ କରାଯାଇଥିବା ଆପ୍ଲିକେସନଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିବା ପାଇଁ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>କୁ ରିମୋଟ ଆକ୍ସେସ ପ୍ରଦାନ କରିବାକୁ ଦିଅନ୍ତୁ।"</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>କୁ, ଏହି ଡିଭାଇସଟି ସଂଯୁକ୍ତ ହୋଇଥିବା ବେଳେ ଏଥିରେ ଇନଷ୍ଟଲ କରାଯାଇଥିବା ଆପ୍ଲିକେସନଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିବା ପାଇଁ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>କୁ ରିମୋଟ ଆକ୍ସେସ ପ୍ରଦାନ କରିବାକୁ ଦିଅନ୍ତୁ।"</string> + <string name="permission_apps" msgid="6142133265286656158">"ଆପ୍ସ"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"ଆପଣଙ୍କ ଫୋନର ଆପ୍ସକୁ ଷ୍ଟ୍ରିମ କରନ୍ତୁ"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"ଆପଣଙ୍କ ଫୋନରୁ ଏହି ସୂଚନାକୁ ଆକ୍ସେସ କରିବା ପାଇଁ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>କୁ ଅନୁମତି ଦିଅନ୍ତୁ"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"କ୍ରସ-ଡିଭାଇସ ସେବାଗୁଡ଼ିକ"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"ଆପଣଙ୍କ ଫୋନର ଫଟୋ, ମିଡିଆ ଏବଂ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିବା ପାଇଁ <xliff:g id="APP_NAME">%1$s</xliff:g> ଆପଣଙ୍କ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ତରଫରୁ ଅନୁମତି ପାଇଁ ଅନୁରୋଧ କରୁଛି"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"ଆପଣଙ୍କ ଫୋନରୁ ଏହି ସୂଚନାକୁ ଆକ୍ସେସ କରିବା ପାଇଁ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>କୁ ଅନୁମତି ଦିଅନ୍ତୁ"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"ଯୋଗାଯୋଗ, ମେସେଜ ଏବଂ ଫଟୋଗୁଡ଼ିକ ପରି ସୂଚନା ସମେତ ସମସ୍ତ ବିଜ୍ଞପ୍ତିକୁ ପଢ଼ିପାରିବ"</string> + <string name="permission_storage" msgid="6831099350839392343">"ଫଟୋ ଏବଂ ମିଡିଆ"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play ସେବାଗୁଡ଼ିକ"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"ଆପଣଙ୍କ ଡିଭାଇସଗୁଡ଼ିକ ମଧ୍ୟରେ ଆପ୍ସକୁ ଷ୍ଟ୍ରିମ କରିବା ପାଇଁ <xliff:g id="APP_NAME">%1$s</xliff:g> ଆପଣଙ୍କ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ତରଫରୁ ଅନୁମତି ପାଇଁ ଅନୁରୋଧ କରୁଛି"</string> <string name="profile_name_generic" msgid="6851028682723034988">"ଡିଭାଇସ୍"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"ଅନୁମତି ଦିଅନ୍ତୁ"</string> <string name="consent_no" msgid="2640796915611404382">"ଅନୁମତି ଦିଅନ୍ତୁ ନାହିଁ"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"ଆପଣଙ୍କ ୱାଚକୁ ଆପ ଅନୁମତିଗୁଡ଼ିକ ଟ୍ରାନ୍ସଫର କରନ୍ତୁ"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"ଆପଣଙ୍କ ୱାଚ ସେଟ ଅପ କରିବାକୁ ସହଜ କରିବା ପାଇଁ, ସେଟଅପ ସମୟରେ ଆପଣଙ୍କର ୱାଚରେ ଇନଷ୍ଟଲ କରାଯାଇଥିବା ଆପଗୁଡ଼ିକ ଆପଣଙ୍କ ଫୋନରେ ଥିବା ଆପଗୁଡ଼ିକ ପରି ସମାନ ଅନୁମତିଗୁଡ଼ିକ ବ୍ୟବହାର କରିବ।\n\n ଏହି ଅନୁମତିଗୁଡ଼ିକରେ ଆପଣଙ୍କ ୱାଚର ମାଇକ୍ରୋଫୋନ ଏବଂ ଲୋକେସନକୁ ଆକ୍ସେସ ଅନ୍ତର୍ଭୁକ୍ତ ହୋଇପାରେ।"</string> + <string name="consent_back" msgid="2560683030046918882">"ପଛକୁ ଫେରନ୍ତୁ"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>ପରି <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong>ରେ ଥିବା ଆପ୍ସକୁ ସମାନ ଅନୁମତିଗୁଡ଼ିକ ଦେବେ?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>ଏହା <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>ରେ ମାଇକ୍ରୋଫୋନ, କ୍ୟାମେରା ଏବଂ ଲୋକେସନ ଆକ୍ସେସ ଓ ଅନ୍ୟ ସମ୍ବେଦନଶୀଳ ଅନୁମତିଗୁଡ଼ିକୁ ଅନ୍ତର୍ଭୁକ୍ତ କରିପାରେ।</p> <p>ଆପଣ <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>ରେ ଯେ କୌଣସି ସମୟରେ ଆପଣଙ୍କ ସେଟିଂସରେ ଏହି ଅନୁମତିଗୁଡ଼ିକୁ ପରିବର୍ତ୍ତନ କରିପାରିବେ।</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-pa/strings.xml b/packages/CompanionDeviceManager/res/values-pa/strings.xml index c28be2543707..bffb7c377cfd 100644 --- a/packages/CompanionDeviceManager/res/values-pa/strings.xml +++ b/packages/CompanionDeviceManager/res/values-pa/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> ਵੱਲੋਂ ਪ੍ਰਬੰਧਿਤ ਕੀਤੇ ਜਾਣ ਲਈ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ਚੁਣੋ"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਨੂੰ ਤੁਹਾਡੀਆਂ ਸੂਚਨਾਵਾਂ ਨਾਲ ਅੰਤਰਕਿਰਿਆ ਕਰਨ ਅਤੇ ਤੁਹਾਡੇ ਫ਼ੋਨ, SMS, ਸੰਪਰਕ ਅਤੇ ਕੈਲੰਡਰ ਦੀਆਂ ਇਜਾਜ਼ਤਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਹੋਵੇਗੀ।"</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਨੂੰ ਤੁਹਾਡੀਆਂ ਸੂਚਨਾਵਾਂ ਨਾਲ ਅੰਤਰਕਿਰਿਆ ਕਰਨ ਅਤੇ ਤੁਹਾਡੇ ਫ਼ੋਨ, SMS, ਸੰਪਰਕ ਅਤੇ ਕੈਲੰਡਰ ਦੀਆਂ ਇਜਾਜ਼ਤਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਹੋਵੇਗੀ।"</string> - <string name="title_app_streaming" msgid="4459136600249308574">"ਕੀ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong&gt ਨੂੰ ਐਪਲੀਕੇਸ਼ਨਾਂ ਸਟ੍ਰੀਮ ਕਰਨ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"ਕਨੈਕਟ ਹੋਣ \'ਤੇ ਇਸ ਫ਼ੋਨ \'ਤੇ ਸਥਾਪਤ ਐਪਲੀਕੇਸ਼ਨਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਲਈ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ਨੂੰ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ਨੂੰ ਰਿਮੋਟ ਪਹੁੰਚ ਮੁਹੱਈਆ ਕਰਵਾਉਣ ਦਿਓ।"</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"ਕਨੈਕਟ ਹੋਣ \'ਤੇ ਇਸ ਟੈਬਲੈੱਟ \'ਤੇ ਸਥਾਪਤ ਐਪਲੀਕੇਸ਼ਨਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਲਈ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ਨੂੰ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ਨੂੰ ਰਿਮੋਟ ਪਹੁੰਚ ਮੁਹੱਈਆ ਕਰਵਾਉਣ ਦਿਓ।"</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"ਕਨੈਕਟ ਹੋਣ \'ਤੇ ਇਸ ਡੀਵਾਈਸ \'ਤੇ ਸਥਾਪਤ ਐਪਲੀਕੇਸ਼ਨਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਲਈ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ਨੂੰ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ਨੂੰ ਰਿਮੋਟ ਪਹੁੰਚ ਮੁਹੱਈਆ ਕਰਵਾਉਣ ਦਿਓ।"</string> + <string name="permission_apps" msgid="6142133265286656158">"ਐਪਾਂ"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"ਆਪਣੇ ਫ਼ੋਨ ਦੀਆਂ ਐਪਾਂ ਨੂੰ ਸਟ੍ਰੀਮ ਕਰੋ"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ਨੂੰ ਤੁਹਾਡੇ ਫ਼ੋਨ ਤੋਂ ਇਸ ਜਾਣਕਾਰੀ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿਓ"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"ਕ੍ਰਾਸ-ਡੀਵਾਈਸ ਸੇਵਾਵਾਂ"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਤੁਹਾਡੇ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ਦੀ ਤਰਫ਼ੋਂ ਤੁਹਾਡੇ ਫ਼ੋਨ ਦੀਆਂ ਫ਼ੋਟੋਆਂ, ਮੀਡੀਆ ਅਤੇ ਸੂਚਨਾਵਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਮੰਗ ਰਹੀ ਹੈ"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ਨੂੰ ਤੁਹਾਡੇ ਫ਼ੋਨ ਤੋਂ ਇਸ ਜਾਣਕਾਰੀ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿਓ"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"ਸੂਚਨਾਵਾਂ"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"ਤੁਸੀਂ ਸਾਰੀਆਂ ਸੂਚਨਾਵਾਂ ਪੜ੍ਹ ਸਕਦੇ ਹੋ, ਜਿਨ੍ਹਾਂ ਵਿੱਚ ਸੰਪਰਕਾਂ, ਸੁਨੇਹਿਆਂ ਅਤੇ ਫ਼ੋਟੋਆਂ ਵਰਗੀ ਜਾਣਕਾਰੀ ਸ਼ਾਮਲ ਹੁੰਦੀ ਹੈ"</string> + <string name="permission_storage" msgid="6831099350839392343">"ਫ਼ੋਟੋਆਂ ਅਤੇ ਮੀਡੀਆ"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play ਸੇਵਾਵਾਂ"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਤੁਹਾਡੇ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ਦੀ ਤਰਫ਼ੋਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸਾਂ ਵਿਚਕਾਰ ਐਪਾਂ ਨੂੰ ਸਟ੍ਰੀਮ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਮੰਗ ਰਹੀ ਹੈ"</string> <string name="profile_name_generic" msgid="6851028682723034988">"ਡੀਵਾਈਸ"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"ਇਜਾਜ਼ਤ ਦਿਓ"</string> <string name="consent_no" msgid="2640796915611404382">"ਇਜਾਜ਼ਤ ਨਾ ਦਿਓ"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"ਐਪ ਇਜਾਜ਼ਤਾਂ ਨੂੰ ਆਪਣੀ ਘੜੀ \'ਤੇ ਟ੍ਰਾਂਸਫ਼ਰ ਕਰੋ"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"ਤੁਹਾਡੀ ਘੜੀ ਦਾ ਸੈੱਟਅੱਪ ਕਰਨਾ ਆਸਾਨ ਬਣਾਉਣ ਲਈ, ਤੁਹਾਡੀ ਘੜੀ \'ਤੇ ਸਥਾਪਤ ਐਪਾਂ ਸੈੱਟਅੱਪ ਦੌਰਾਨ ਉਹੀ ਇਜਾਜ਼ਤਾਂ ਵਰਤਣਗੀਆਂ ਜੋ ਤੁਹਾਡਾ ਫ਼ੋਨ ਵਰਤਦਾ ਹੈ।\n\n ਇਨ੍ਹਾਂ ਇਜਾਜ਼ਤਾਂ ਵਿੱਚ ਤੁਹਾਡੀ ਘੜੀ ਦੇ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਅਤੇ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚ ਸ਼ਾਮਲ ਹੋ ਸਕਦੀ ਹੈ।"</string> + <string name="consent_back" msgid="2560683030046918882">"ਪਿੱਛੇ"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"ਕੀ <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> \'ਤੇ ਮੌਜੂਦ ਐਪਾਂ ਨੂੰ <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> \'ਤੇ ਮੌਜੂਦ ਐਪਾਂ ਵਾਂਗ ਇਜਾਜ਼ਤਾਂ ਦੇਣੀਆਂ ਹਨ?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>ਇਸ ਵਿੱਚ ਮਾਈਕ੍ਰੋਫ਼ੋਨ, ਕੈਮਰਾ, ਟਿਕਾਣਾ ਪਹੁੰਚ ਅਤੇ <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> \'ਤੇ ਮੌਜੂਦ ਹੋਰ ਸੰਵੇਦਨਸ਼ੀਲ ਜਾਣਕਾਰੀ ਤੱਕ ਪਹੁੰਚ ਸੰਬੰਧੀ ਇਜਾਜ਼ਤਾਂ ਸ਼ਾਮਲ ਹੋ ਸਕਦੀਆਂ ਹਨ।</p> <p>ਤੁਸੀਂ <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> \'ਤੇ ਮੌਜੂਦ ਆਪਣੀਆਂ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਜਾ ਕੇ ਕਦੇ ਵੀ ਇਨ੍ਹਾਂ ਇਜਾਜ਼ਤਾਂ ਨੂੰ ਬਦਲ ਸਕਦੇ ਹੋ।</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-pl/strings.xml b/packages/CompanionDeviceManager/res/values-pl/strings.xml index f9fd206250d9..704e402548dc 100644 --- a/packages/CompanionDeviceManager/res/values-pl/strings.xml +++ b/packages/CompanionDeviceManager/res/values-pl/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Wybierz profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, którym ma zarządzać aplikacja <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> będzie mogła korzystać z powiadomień oraz uprawnień dotyczących Telefonu, SMS-ów, Kontaktów i Kalendarza."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> będzie mogła korzystać z powiadomień oraz uprawnień dotyczących Telefonu, SMS-ów, Kontaktów i Kalendarza."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Zezwolić aplikacji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> na strumieniowanie danych z aplikacji?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Zezwól na zapewnianie przez aplikację <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> zdalnego dostępu do aplikacji zainstalowanych na telefonie <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> po połączeniu jej z tym telefonem."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Zezwól na zapewnianie przez aplikację <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> zdalnego dostępu do aplikacji zainstalowanych na tablecie <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> po połączeniu jej z tym tabletem."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Zezwól na zapewnianie przez aplikację <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> zdalnego dostępu do aplikacji zainstalowanych na urządzeniu <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> po połączeniu jej z urządzeniem."</string> + <string name="permission_apps" msgid="6142133265286656158">"Aplikacje"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Odtwarzaj strumieniowo aplikacje z telefonu"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Zezwól aplikacji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> na dostęp do tych informacji na Twoim telefonie"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Usługi na innym urządzeniu"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> prosi w imieniu urządzenia <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> o uprawnienia dotyczące dostępu do zdjęć, multimediów i powiadomień na telefonie"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Zezwól aplikacji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> na dostęp do tych informacji na Twoim telefonie"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Powiadomienia"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Może odczytywać wszystkie powiadomienia, w tym informacje takie jak kontakty, wiadomości i zdjęcia"</string> + <string name="permission_storage" msgid="6831099350839392343">"Zdjęcia i multimedia"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Usługi Google Play"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> prosi w imieniu urządzenia <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> o uprawnienia dotyczące strumieniowego odtwarzania aplikacji między urządzeniami"</string> <string name="profile_name_generic" msgid="6851028682723034988">"urządzenie"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Zezwól"</string> <string name="consent_no" msgid="2640796915611404382">"Nie zezwalaj"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Przenieś uprawnienia aplikacji na zegarek"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Aby łatwiej było skonfigurować zegarek, aplikacje zainstalowane na nim podczas konfiguracji będą korzystały z tych samych uprawnień co telefon.\n\n Może to oznaczać dostęp do mikrofonu i lokalizacji na zegarku."</string> + <string name="consent_back" msgid="2560683030046918882">"Wstecz"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Czy aplikacjom na urządzeniu <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> przyznać te same uprawnienia co na urządzeniu <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Mogą one obejmować dane dostęp do Mikrofonu, Aparatu i lokalizacji oraz inne uprawnienia newralgiczne na urządzeniu <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Możesz w dowolnym momencie zmienić uprawnienia na urządzeniu <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml b/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml index 161188c70c6c..6bd9bf996955 100644 --- a/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml +++ b/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Escolha um <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para ser gerenciado pelo app <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> poderá interagir com suas notificações e acessar as permissões do Telefone, de SMS, de Contatos e da Agenda."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> poderá interagir com suas notificações e acessar as permissões do Telefone, de SMS, de Contatos e da Agenda."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Permitir que o app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> faça streaming de aplicativos?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Permita que o app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> conceda ao <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> acesso remoto aos aplicativos instalados no smartphone quando ele estiver conectado."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Permita que o app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> conceda ao <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> acesso remoto aos aplicativos instalados no tablet quando ele estiver conectado."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Permita que o app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> conceda ao <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> acesso remoto aos aplicativos instalados no dispositivo quando ele estiver conectado."</string> + <string name="permission_apps" msgid="6142133265286656158">"Apps"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Faça streaming dos apps do seu smartphone"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Permitir que o app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acesse essas informações do smartphone"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Serviços entre dispositivos"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para acessar fotos, mídia e notificações do smartphone."</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Autorizar que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acesse essas informações do smartphone"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Notificações"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Pode ler todas as notificações, incluindo informações como contatos, mensagens e fotos"</string> + <string name="permission_storage" msgid="6831099350839392343">"Fotos e mídia"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play Services"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para fazer streaming de apps entre seus dispositivos"</string> <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Permitir"</string> <string name="consent_no" msgid="2640796915611404382">"Não permitir"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transferir as permissões de apps para o relógio"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Para facilitar a configuração do relógio, os apps instalados nele durante a configuração vão usar as mesmas permissões que o smartphone.\n\n Essas permissões podem incluir acesso ao microfone ou à localização do relógio."</string> + <string name="consent_back" msgid="2560683030046918882">"Voltar"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Dar aos apps no dispositivo <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> as mesmas permissões do dispositivo <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Isso pode incluir acesso a microfone, câmera e localização e outras permissões sensíveis no <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Você pode mudar essas permissões a qualquer momento nas configurações do <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml b/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml index 9124a405198a..0b1ed8d7ef5c 100644 --- a/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml +++ b/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Escolha um <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para ser gerido pela app <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> poderá interagir com as suas notificações e aceder às autorizações do Telefone, SMS, Contactos e Calendário."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> poderá interagir com as suas notificações e aceder às autorizações do Telefone, SMS, Contactos e Calendário."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Permitir que a app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> faça stream de aplicações?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Permita que a app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> forneça acesso remoto ao <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> para aceder a aplicações instaladas neste telemóvel quando estiver ligado."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Permita que a app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> forneça acesso remoto ao <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> para aceder a aplicações instaladas neste tablet quando estiver ligado."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Permita que a app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> forneça acesso remoto ao <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> para aceder a aplicações instaladas neste dispositivo quando estiver ligado."</string> + <string name="permission_apps" msgid="6142133265286656158">"Apps"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Faça stream das apps do telemóvel"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Permita que a app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> aceda a estas informações do seu telemóvel"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Serviços entre dispositivos"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> está a pedir autorização em nome do seu dispositivo <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para aceder às fotos, conteúdo multimédia e notificações do seu telemóvel"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Permita que a app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> aceda a estas informações do seu telemóvel"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Notificações"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Pode ler todas as notificações, incluindo informações como contratos, mensagens e fotos"</string> + <string name="permission_storage" msgid="6831099350839392343">"Fotos e multimédia"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Serviços do Google Play"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> está a pedir autorização em nome do seu dispositivo <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para fazer stream de apps entre os seus dispositivos"</string> <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Permitir"</string> <string name="consent_no" msgid="2640796915611404382">"Não permitir"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transfira as autorizações da app para o seu relógio"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Para facilitar a configuração do seu relógio, as apps instaladas no mesmo durante a configuração utilizarão as mesmas autorizações que o telemóvel.\n\n Estas autorizações podem incluir o acesso ao microfone e à localização do seu relógio."</string> + <string name="consent_back" msgid="2560683030046918882">"Voltar"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Atribuir às apps no dispositivo <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> as mesmas autorizações que no dispositivo <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Isto pode incluir o acesso ao microfone, câmara e localização, bem como a outras autorizações confidenciais no dispositivo <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Pode alterar estas autorizações em qualquer altura nas Definições do dispositivo <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-pt/strings.xml b/packages/CompanionDeviceManager/res/values-pt/strings.xml index 161188c70c6c..6bd9bf996955 100644 --- a/packages/CompanionDeviceManager/res/values-pt/strings.xml +++ b/packages/CompanionDeviceManager/res/values-pt/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Escolha um <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para ser gerenciado pelo app <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> poderá interagir com suas notificações e acessar as permissões do Telefone, de SMS, de Contatos e da Agenda."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> poderá interagir com suas notificações e acessar as permissões do Telefone, de SMS, de Contatos e da Agenda."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Permitir que o app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> faça streaming de aplicativos?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Permita que o app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> conceda ao <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> acesso remoto aos aplicativos instalados no smartphone quando ele estiver conectado."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Permita que o app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> conceda ao <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> acesso remoto aos aplicativos instalados no tablet quando ele estiver conectado."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Permita que o app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> conceda ao <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> acesso remoto aos aplicativos instalados no dispositivo quando ele estiver conectado."</string> + <string name="permission_apps" msgid="6142133265286656158">"Apps"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Faça streaming dos apps do seu smartphone"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Permitir que o app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acesse essas informações do smartphone"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Serviços entre dispositivos"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para acessar fotos, mídia e notificações do smartphone."</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Autorizar que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acesse essas informações do smartphone"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Notificações"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Pode ler todas as notificações, incluindo informações como contatos, mensagens e fotos"</string> + <string name="permission_storage" msgid="6831099350839392343">"Fotos e mídia"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play Services"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para fazer streaming de apps entre seus dispositivos"</string> <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Permitir"</string> <string name="consent_no" msgid="2640796915611404382">"Não permitir"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transferir as permissões de apps para o relógio"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Para facilitar a configuração do relógio, os apps instalados nele durante a configuração vão usar as mesmas permissões que o smartphone.\n\n Essas permissões podem incluir acesso ao microfone ou à localização do relógio."</string> + <string name="consent_back" msgid="2560683030046918882">"Voltar"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Dar aos apps no dispositivo <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> as mesmas permissões do dispositivo <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Isso pode incluir acesso a microfone, câmera e localização e outras permissões sensíveis no <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Você pode mudar essas permissões a qualquer momento nas configurações do <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-ro/strings.xml b/packages/CompanionDeviceManager/res/values-ro/strings.xml index da7ae9e0f1bd..422787197afd 100644 --- a/packages/CompanionDeviceManager/res/values-ro/strings.xml +++ b/packages/CompanionDeviceManager/res/values-ro/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Alegeți un profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g> pe care să îl gestioneze <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> va putea să interacționeze cu notificările dvs. și să vă acceseze permisiunile pentru Telefon, SMS-uri, Agendă și Calendar."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> va putea să interacționeze cu notificările dvs. și să vă acceseze permisiunile pentru Telefon, SMS-uri, Agendă și Calendar."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Lăsați <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> să redea în stream aplicații?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Lăsați <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> să ofere acces la distanță pentru <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ca să se poată accesa aplicațiile instalate pe acest telefon când se conectează utilizatorul."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Lăsați <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> să ofere acces la distanță pentru <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ca să se poată accesa aplicațiile instalate pe această tabletă când se conectează utilizatorul."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Lăsați <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> să ofere acces la distanță pentru <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ca să se poată accesa aplicațiile instalate pe acest dispozitiv când se conectează utilizatorul."</string> + <string name="permission_apps" msgid="6142133265286656158">"Aplicații"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Să redea în stream aplicațiile telefonului"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Permiteți ca <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> să acceseze aceste informații de pe telefon"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Servicii pe mai multe dispozitive"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> solicită permisiunea pentru <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> de a accesa fotografiile, conținutul media și notificările de pe telefon"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Permiteți ca <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> să acceseze aceste informații de pe telefon"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Notificări"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Poate să citească toate notificările, inclusiv informații cum ar fi agenda, mesajele și fotografiile"</string> + <string name="permission_storage" msgid="6831099350839392343">"Fotografii și media"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Servicii Google Play"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> solicită permisiunea pentru <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> de a reda în stream aplicații între dispozitivele dvs."</string> <string name="profile_name_generic" msgid="6851028682723034988">"dispozitiv"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Permiteți"</string> <string name="consent_no" msgid="2640796915611404382">"Nu permiteți"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transferați permisiunile pentru aplicații pe ceas"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Ca să configurați mai ușor ceasul, aplicațiile instalate pe ceas în timpul procesului de configurare vor folosi aceleași permisiuni ca telefonul.\n\n Între acestea se poate număra accesul la microfonul și locația ceasului."</string> + <string name="consent_back" msgid="2560683030046918882">"Înapoi"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Oferiți aplicațiilor de pe <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> aceleași permisiuni ca pe <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Aici pot fi incluse accesul la microfon, la camera foto, la locație și alte permisiuni de accesare a informațiilor sensibile de pe <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Puteți modifica oricând aceste permisiuni din Setările de pe <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-ru/strings.xml b/packages/CompanionDeviceManager/res/values-ru/strings.xml index dbb09c9e7c96..bd50b08c3c3f 100644 --- a/packages/CompanionDeviceManager/res/values-ru/strings.xml +++ b/packages/CompanionDeviceManager/res/values-ru/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Выберите устройство (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>), которым будет управлять приложение <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"Приложению \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" будет предоставлен доступ к уведомлениям, а также следующие разрешения: телефон, SMS, контакты и календарь."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"Приложению \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" будет предоставлен доступ к уведомлениям, а также следующие разрешения: телефон, SMS, контакты и календарь."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Разрешить приложению <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> транслировать приложения?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Разрешить приложению <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> при наличии подключения предоставить устройству <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> удаленный доступ к приложениям, установленным на этом телефоне."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Разрешить приложению <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> при наличии подключения предоставить устройству <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> удаленный доступ к приложениям, установленным на этом планшете."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Разрешить приложению <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> при наличии подключения предоставить устройству <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> удаленный доступ к приложениям, установленным на этом устройстве."</string> + <string name="permission_apps" msgid="6142133265286656158">"Приложения"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Трансляция приложений с телефона."</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Разрешите приложению <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> получать эту информацию с вашего телефона"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Сервисы стриминга приложений"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" запрашивает разрешение от имени вашего устройства <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, чтобы получить доступ к фотографиям, медиаконтенту и уведомлениям на телефоне."</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Разрешите приложению <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> получать эту информацию с вашего телефона"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Уведомления"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Чтение всех уведомлений, в том числе сведений о контактах, сообщениях и фотографиях."</string> + <string name="permission_storage" msgid="6831099350839392343">"Фотографии и медиафайлы"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Сервисы Google Play"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" запрашивает доступ от имени вашего устройства <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, чтобы транслировать приложения между вашими устройствами."</string> <string name="profile_name_generic" msgid="6851028682723034988">"устройство"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Разрешить"</string> <string name="consent_no" msgid="2640796915611404382">"Запретить"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Перенос разрешений для приложений на часы"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Для приложений, установленных на часы во время настройки, будут использоваться те же разрешения, что и на телефоне.\n\n Например, может быть включен доступ к микрофону на часах или сведениям о местоположении."</string> + <string name="consent_back" msgid="2560683030046918882">"Назад"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Предоставить приложениям на устройстве <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> те же разрешения, что на устройстве <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Сюда может входить доступ к микрофону, камере и данным о местоположении, а также другие разрешения на доступ к конфиденциальной информации на устройстве <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Вы можете в любое время изменить разрешения в настройках устройства <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-si/strings.xml b/packages/CompanionDeviceManager/res/values-si/strings.xml index a3de2a393181..440135b364cd 100644 --- a/packages/CompanionDeviceManager/res/values-si/strings.xml +++ b/packages/CompanionDeviceManager/res/values-si/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> මගින් කළමනාකරණය කරනු ලැබීමට <xliff:g id="PROFILE_NAME">%1$s</xliff:g>ක් තෝරන්න"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ඔබගේ දැනුම්දීම් සමඟ අන්තර්ක්රියා කිරීමට සහ ඔබගේ දුරකථනය, කෙටි පණිවුඩ, සම්බන්ධතා සහ දින දර්ශන අවසර වෙත ප්රවේශ වීමට ඉඩ දෙනු ඇත."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ඔබගේ දැනුම්දීම් සමඟ අන්තර්ක්රියා කිරීමට සහ ඔබගේ දුරකථනය, කෙටි පණිවුඩ, සම්බන්ධතා සහ දින දර්ශන අවසර වෙත ප්රවේශ වීමට ඉඩ දෙනු ඇත."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> හට යෙදුම් ප්රවාහ කිරීමට ඉඩ දෙන්නද?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"සම්බන්ධ වූ විට මෙම දුරකථනයේ ස්ථාපනය කර ඇති යෙදුම් වෙත ප්රවේශ වීමට <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> හට <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> හට දුරස්ථ ප්රවේශය ලබා දීමට ඉඩ දෙන්න."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"සම්බන්ධ වූ විට මෙම ටැබ්ලටයේ ස්ථාපනය කර ඇති යෙදුම් වෙත ප්රවේශ වීමට <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> හට <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> හට දුරස්ථ ප්රවේශය ලබා දීමට ඉඩ දෙන්න."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"සම්බන්ධ වූ විට මෙම උපාංගයේ ස්ථාපනය කර ඇති යෙදුම් වෙත ප්රවේශ වීමට <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> හට <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> හට දුරස්ථ ප්රවේශය ලබා දීමට ඉඩ දෙන්න."</string> + <string name="permission_apps" msgid="6142133265286656158">"යෙදුම්"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"ඔබගේ දුරකථනයේ යෙදුම් ප්රවාහ කරන්න"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> හට ඔබගේ දුරකථනයෙන් මෙම තොරතුරුවලට ප්රවේශ වීමට ඉඩ දෙන්න"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"හරස්-උපාංග සේවා"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> ඔබගේ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> වෙනුවෙන් ඔබගේ දුරකථනයෙහි ඡායාරූප, මාධ්ය සහ දැනුම්දීම් වෙත ප්රවේශ වීමට අවසරය ඉල්ලමින් සිටී"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> හට ඔබගේ දුරකථනයෙන් මෙම තොරතුරුවලට ප්රවේශ වීමට ඉඩ දෙන්න"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"දැනුම්දීම්"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"සම්බන්ධතා, පණිවිඩ සහ ඡායාරූප වැනි තොරතුරු ඇතුළුව සියලු දැනුම්දීම් කියවිය හැකිය"</string> + <string name="permission_storage" msgid="6831099350839392343">"ඡායාරූප සහ මාධ්ය"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play සේවා"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> ඔබගේ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> වෙනුවෙන් ඔබගේ උපාංග අතර යෙදුම් ප්රවාහ කිරීමට අවසරය ඉල්ලමින් සිටී"</string> <string name="profile_name_generic" msgid="6851028682723034988">"උපාංගය"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"ඉඩ දෙන්න"</string> <string name="consent_no" msgid="2640796915611404382">"ඉඩ නොදෙන්න"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"ඔබගේ ඔරලෝසුවට යෙදුම් අවසර මාරු කිරීම"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"ඔබගේ ඔරලෝසුව පිහිටුවීම පහසු කිරීමට, පිහිටුවීමේදී ඔබගේ ඔරලෝසුවේ ස්ථාපනය කර ඇති යෙදුම් ඔබගේ දුරකථනයට සමාන අවසර භාවිත කරනු ඇත.\n\n මෙම අවසරවලට ඔබගේ ඔරලෝසුවේ මයික්රෆෝනයට සහ ස්ථානයට ප්රවේශය ඇතුළත් විය හැකිය."</string> + <string name="consent_back" msgid="2560683030046918882">"ආපසු"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> the හි යෙදුම්වලට <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> හි අවසරම දෙන්නද?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>මෙයට මයික්රෆෝනය, කැමරාව සහ ස්ථාන ප්රවේශය සහ <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> හි අනෙකුත් සංවේදී අවසර ඇතුළත් විය හැකිය.</p> <p>ඔබට ඔබගේ සැකසීම් තුළ <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> හිදී ඕනෑම වේලාවක මෙම අවසර වෙනස් කළ හැකිය.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-sk/strings.xml b/packages/CompanionDeviceManager/res/values-sk/strings.xml index dd75ef590913..150b3183dc5f 100644 --- a/packages/CompanionDeviceManager/res/values-sk/strings.xml +++ b/packages/CompanionDeviceManager/res/values-sk/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Vyberte profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, ktorý bude spravovať aplikácia <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> bude môcť interagovať s vašimi upozorneniami a získavať prístup k povoleniam telefónu, SMS, kontaktov a kalendára."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> bude môcť interagovať s vašimi upozorneniami a získavať prístup k povoleniam telefónu, SMS, kontaktov a kalendára."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Chcete aplikácii <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> povoliť streamovanie aplikácií?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Povoľte aplikácii <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> vzdialený prístup k telefónu <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>, aby mala po pripojení prístup k aplikáciám, ktoré sú v ňom nainštalované."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Povoľte aplikácii <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> vzdialený prístup k tabletu <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>, aby mala po pripojení prístup k aplikáciám, ktoré sú v ňom nainštalované."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Povoľte aplikácii <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> vzdialený prístup k zariadeniu <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>, aby mala po pripojení prístup k aplikáciám, ktoré sú v ňom nainštalované."</string> + <string name="permission_apps" msgid="6142133265286656158">"Aplikácie"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Streamujte aplikácie telefónu"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Povoľte aplikácii <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> prístup k týmto informáciám z vášho telefónu"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Služby pre viacero zariadení"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> vyžaduje povolenie na prístup k fotkám, médiám a upozorneniam vášho telefónu v mene tohto zariadenia (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>)"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Povoľte aplikácii <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> prístup k týmto informáciám z vášho telefónu"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Upozornenia"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Môže čítať všetky upozornenia vrátane informácií, ako sú kontakty, správy a fotky"</string> + <string name="permission_storage" msgid="6831099350839392343">"Fotky a médiá"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Služby Google Play"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> vyžaduje povolenie na streamovanie aplikácií medzi vašimi zariadeniami v mene tohto zariadenia (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>)"</string> <string name="profile_name_generic" msgid="6851028682723034988">"zariadenie"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Povoliť"</string> <string name="consent_no" msgid="2640796915611404382">"Nepovoliť"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Presun povolení aplikácie do hodiniek"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"V rámci zjednodušenia nastavenia hodiniek budú aplikácie nainštalované do hodiniek pri nastavovaní používať rovnaké povolenia ako váš telefón.\n\n Tieto povolenia môžu zahrnovať prístup k mikrofónu a polohe hodiniek."</string> + <string name="consent_back" msgid="2560683030046918882">"Späť"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Chcete udeliť aplikáciám v zariadení <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> rovnaké povolenia ako v zariadení <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Môžu zahŕňať prístup k mikrofónu, kamere a polohe a ďalšie citlivé povolenia v zariadení <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Tieto povolenia môžete kedykoľvek zmeniť v Nastaveniach v zariadení <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-sl/strings.xml b/packages/CompanionDeviceManager/res/values-sl/strings.xml index 7cb5fb58fb60..49832fe6226d 100644 --- a/packages/CompanionDeviceManager/res/values-sl/strings.xml +++ b/packages/CompanionDeviceManager/res/values-sl/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Izbira naprave <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, ki jo bo upravljala aplikacija <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"Aplikaciji <xliff:g id="APP_NAME">%1$s</xliff:g> bosta omogočena interakcija z obvestili in dostop do dovoljenj za telefon, sporočila SMS, stike in koledar."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"Aplikaciji <xliff:g id="APP_NAME">%1$s</xliff:g> bosta omogočena interakcija z obvestili in dostop do dovoljenj za telefon, sporočila SMS, stike in koledar."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Želite aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> dovoliti pretočno predvajanje aplikacij?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> dovoli oddaljen dostop do telefona <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> za dostop do aplikacij, nameščenih v tem telefonu, ko je povezan v internet."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> dovoli oddaljen dostop do tabličnega računalnika <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> za dostop do aplikacij, nameščenih v tem tabličnem računalniku, ko je povezan v internet."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> dovoli oddaljen dostop do naprave <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> za dostop do aplikacij, nameščenih v tej napravi, ko je povezana v internet."</string> + <string name="permission_apps" msgid="6142133265286656158">"Aplikacije"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Pretočno predvajanje aplikacij telefona"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Dovolite, da <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> dostopa do teh podatkov v vašem telefonu."</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Storitve za zunanje naprave"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> v imenu naprave »<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>« zahteva dovoljenje za dostop do fotografij, predstavnosti in obvestil v telefonu."</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Dovolite, da <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> dostopa do teh podatkov v vašem telefonu."</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Obvestila"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Lahko bere vsa obvestila, vključno s podatki, kot so stiki, sporočila in fotografije."</string> + <string name="permission_storage" msgid="6831099350839392343">"Fotografije in predstavnost"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Storitve Google Play"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> v imenu naprave »<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>« zahteva dovoljenje za pretočno predvajanje aplikacij v vaših napravah."</string> <string name="profile_name_generic" msgid="6851028682723034988">"naprava"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Dovoli"</string> <string name="consent_no" msgid="2640796915611404382">"Ne dovoli"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Prenos dovoljenj za aplikacije v uro"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Za lažjo nastavitev ure bodo aplikacije, ki so bile med nastavljanjem nameščene v uri, uporabljale enaka dovoljenja kot tiste v telefonu.\n\n Ta dovoljenja lahko vključujejo dostop do mikrofona in lokacije ure."</string> + <string name="consent_back" msgid="2560683030046918882">"Nazaj"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Ali želite aplikacijam v napravi <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> odobriti enaka dovoljenja kot v napravi <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>To lahko vključuje dostop do mikrofona, fotoaparata in lokacije ter druga občutljiva dovoljenja v napravi <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Ta dovoljenja lahko kadar koli spremenite v nastavitvah v napravi <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-sq/strings.xml b/packages/CompanionDeviceManager/res/values-sq/strings.xml index 62c711abf398..e09180715257 100644 --- a/packages/CompanionDeviceManager/res/values-sq/strings.xml +++ b/packages/CompanionDeviceManager/res/values-sq/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Zgjidh një profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g> që do të menaxhohet nga <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> do të lejohet të ndërveprojë me njoftimet e tua dhe të ketë qasje te lejet e \"Telefonit\", \"SMS-ve\", \"Kontakteve\" dhe \"Kalendarit\"."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> do të lejohet të ndërveprojë me njoftimet e tua dhe të ketë qasje te lejet e \"Telefonit\", \"SMS-ve\", \"Kontakteve\" dhe \"Kalendarit\"."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Të lejohet që <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> të transmetojë aplikacionet?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Lejo që <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> të ofrojë <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> qasje në distancë për të pasur qasje në aplikacionet e instaluara në këtë telefon kur lidhet."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Lejo që <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> të ofrojë <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> qasje në distancë për të pasur qasje në aplikacionet e instaluara në këtë tablet kur lidhet."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Lejo që <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> t\'i ofrojë <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> qasje në distancë për të pasur qasje në aplikacionet e instaluara në këtë pajisje kur lidhet."</string> + <string name="permission_apps" msgid="6142133265286656158">"Aplikacionet"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Transmeto aplikacionet e telefonit tënd"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Lejo që <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> të ketë qasje në këtë informacion nga telefoni yt"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Shërbimet mes pajisjeve"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> po kërkon leje në emër të <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> për të marrë qasje te fotografitë, media dhe njoftimet e telefonit tënd"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Lejo që <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> të ketë qasje në këtë informacion nga telefoni yt"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Njoftimet"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Mund të lexojë të gjitha njoftimet, duke përfshirë informacione si kontaktet, mesazhet dhe fotografitë"</string> + <string name="permission_storage" msgid="6831099350839392343">"Fotografitë dhe media"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Shërbimet e Google Play"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> po kërkon leje në emër të <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> për të transmetuar aplikacione ndërmjet pajisjeve të tua"</string> <string name="profile_name_generic" msgid="6851028682723034988">"pajisja"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Lejo"</string> <string name="consent_no" msgid="2640796915611404382">"Mos lejo"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Transfero lejet e aplikacionit te ora jote"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Për ta bërë më të lehtë konfigurimin e orës, aplikacionet e instaluara në orën tënde gjatë konfigurimit do të përdorin të njëjtat leje si telefoni yt.\n\n Këto leje mund të përfshijnë qasje në mikrofonin dhe vendndodhjen e orës."</string> + <string name="consent_back" msgid="2560683030046918882">"Pas"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"T\'i jepen aplikacioneve në <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> të njëjtat leje si në <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Kjo mund të përfshijë qasjen te \"Mikrofoni\", \"Kamera\", \"Vendndodhja\" dhe leje të tjera për informacione delikate në <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p&gtTi mund t\'i ndryshosh këto leje në çdo kohë te \"Cilësimet\" në <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-sr/strings.xml b/packages/CompanionDeviceManager/res/values-sr/strings.xml index 8d51c62fd3e7..8e50084679ab 100644 --- a/packages/CompanionDeviceManager/res/values-sr/strings.xml +++ b/packages/CompanionDeviceManager/res/values-sr/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Одаберите профил <xliff:g id="PROFILE_NAME">%1$s</xliff:g> којим ће управљати апликација <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ће добити дозволу за интеракцију са обавештењима и приступ дозволама за телефон, SMS поруке, контакте и календар."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ће добити дозволу за интеракцију са обавештењима и приступ дозволама за телефон, SMS поруке, контакте и календар."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Желите да дозволите апликацији <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да стримује апликације?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Дозволите апликацији <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да даљински приступа апликацијама инсталираним на телефону <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> када је повезан."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Дозволите апликацији <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да даљински приступа апликацијама инсталираним на таблету <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> када је повезан."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Дозволите апликацији <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да даљински приступа апликацијама инсталираним на уређају <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> када је повезан."</string> + <string name="permission_apps" msgid="6142133265286656158">"Апликације"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Стримујте апликације на телефону"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Дозволите да <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> приступа овим информацијама са телефона"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Услуге на више уређаја"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> захтева дозволу у име уређаја <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> за приступ сликама, медијском садржају и обавештењима са телефона"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Дозволите да <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> приступа овим информацијама са телефона"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Обавештења"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Може да чита сва обавештења, укључујући информације попут контаката, порука и слика"</string> + <string name="permission_storage" msgid="6831099350839392343">"Слике и медији"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play услуге"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> захтева дозволу у име уређаја <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> за стримовање апликација између уређаја"</string> <string name="profile_name_generic" msgid="6851028682723034988">"уређај"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Дозволи"</string> <string name="consent_no" msgid="2640796915611404382">"Не дозволи"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Пренесите дозволе за апликације на сат"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Да бисмо поједноставили подешавање сата, апликације инсталиране на сату током подешавања ће користити исте дозволе као телефон.\n\n Те дозволе могу да обухватају приступ микрофону и локацији сата."</string> + <string name="consent_back" msgid="2560683030046918882">"Назад"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Апликцијама на уређају <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> дајте све дозволе као на уређају <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>То може да обухвата приступ микрофону, камери и локацији, као и другим осетљивим дозволама на уређају <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>У сваком тренутку можете да промените те дозволе у Подешавањима на уређају <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-sv/strings.xml b/packages/CompanionDeviceManager/res/values-sv/strings.xml index ca1ec8769675..31f861d09837 100644 --- a/packages/CompanionDeviceManager/res/values-sv/strings.xml +++ b/packages/CompanionDeviceManager/res/values-sv/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Välj en <xliff:g id="PROFILE_NAME">%1$s</xliff:g> för hantering av <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> får behörighet att interagera med dina aviseringar och komma åt behörigheterna för Telefon, Sms, Kontakter och Kalender."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> får behörighet att interagera med dina aviseringar och komma åt behörigheterna för Telefon, Sms, Kontakter och Kalender."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Vill du tillåta att <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> streamar appar?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Låt <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ge <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> fjärråtkomst till åt appar som är installerade på den här telefonen när den är ansluten."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Låt <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ge <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> fjärråtkomst till appar som är installerade på den här surfplattan när den är ansluten."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Låt <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ge <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> fjärråtkomst till appar som är installerade på den här enheten när den är ansluten."</string> + <string name="permission_apps" msgid="6142133265286656158">"Appar"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Streama telefonens appar"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Ge <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> åtkomstbehörighet till denna information på telefonen"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Tjänster för flera enheter"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> begär behörighet att ge <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> åtkomst till foton, mediefiler och aviseringar på telefonen"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Ge <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> åtkomstbehörighet till denna information på telefonen"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Aviseringar"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Kan läsa alla aviseringar, inklusive information som kontakter, meddelanden och foton"</string> + <string name="permission_storage" msgid="6831099350839392343">"Foton och media"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play-tjänster"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> begär behörighet att låta <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> streama appar mellan enheter"</string> <string name="profile_name_generic" msgid="6851028682723034988">"enhet"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Tillåt"</string> <string name="consent_no" msgid="2640796915611404382">"Tillåt inte"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Överför appbehörigheter till klockan"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Appar som installeras på klockan under konfigureringen får samma behörigheter som de har på telefonen så att konfigureringen ska bli enklare.\n\n Behörigheterna kan omfatta åtkomst till klockans mikrofon och plats."</string> + <string name="consent_back" msgid="2560683030046918882">"Tillbaka"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Vill du ge apparna på <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> samma behörigheter som de har på <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Det kan gälla behörighet till mikrofon, kamera och plats och åtkomstbehörighet till andra känsliga uppgifter på <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Du kan när som helst ändra behörigheterna i inställningarna på <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.lt;/p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-sw/strings.xml b/packages/CompanionDeviceManager/res/values-sw/strings.xml index cf9260087bd2..8ae285fe642a 100644 --- a/packages/CompanionDeviceManager/res/values-sw/strings.xml +++ b/packages/CompanionDeviceManager/res/values-sw/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Chagua <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ili idhibitiwe na <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> itaruhusiwa kufikia arifa zako na kufikia ruhusa za Simu, SMS, Anwani na Kalenda yako."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> itaruhusiwa kufikia arifa zako na kufikia ruhusa za Simu, SMS, Anwani na Kalenda yako."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Ungependa kuruhusu <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> itiririshe programu?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Ruhusu <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> iipe <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ufikiaji wa mbali wa programu zilizosakinishwa kwenye simu hii wakati imeunganishwa."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Ruhusu <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> iipe <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ufikiaji wa mbali wa programu zilizosakinishwa kwenye kompyuta hii kibao wakati imeunganishwa."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Ruhusu <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> iipe <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ufikiaji wa mbali wa programu zilizosakinishwa kwenye kifaa hiki wakati kimeunganishwa."</string> + <string name="permission_apps" msgid="6142133265286656158">"Programu"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Tiririsha programu za simu yako"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Ruhusu <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ifikie maelezo haya kutoka kwenye simu yako"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Huduma za kifaa kilichounganishwa kwingine"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> inaomba ruhusa kwa niaba ya <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> yako ili kufikia picha, maudhui na arifa za simu yako"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Ruhusu <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ifikie maelezo haya kutoka kwenye simu yako"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Arifa"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Inaweza kusoma arifa zote, ikiwa ni pamoja na maelezo kama vile anwani, ujumbe na picha"</string> + <string name="permission_storage" msgid="6831099350839392343">"Picha na maudhui"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Huduma za Google Play"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> inaomba ruhusa kwa niaba ya <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> yako ili kutiririsha programu kati ya vifaa vyako"</string> <string name="profile_name_generic" msgid="6851028682723034988">"kifaa"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Ruhusu"</string> <string name="consent_no" msgid="2640796915611404382">"Usiruhusu"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Hamishia idhini za programu kwenye saa yako"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Ili kurahisisha kuweka mipangilio ya saa yako, programu ambazo zimesakinishwa kwenye saa yako wakati wa kuweka mipangilio zitatumia ruhusa sawa na zinazotumika kwenye simu yako.\n\n Ruhusa hizi huenda zikajumuisha ufikiaji wa maikrofoni ya saa yako na maelezo ya mahali ilipo saa yako."</string> + <string name="consent_back" msgid="2560683030046918882">"Nyuma"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Zipatie programu katika <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> ruhusa ile ile kama kwenye <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Hii huenda ikajumuisha ufikiaji wa Maikrofoni, Kamera na Mahali, pamoja na ruhusa nyingine nyeti kwenye <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Unaweza kubadilisha ruhusa hizi muda wowote katika Mipangilio yako kwenye <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-ta/strings.xml b/packages/CompanionDeviceManager/res/values-ta/strings.xml index b86ea1cffacf..3e3daa94a653 100644 --- a/packages/CompanionDeviceManager/res/values-ta/strings.xml +++ b/packages/CompanionDeviceManager/res/values-ta/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> ஆப்ஸ் நிர்வகிக்கக்கூடிய <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ஐத் தேர்ந்தெடுங்கள்"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"உங்கள் அறிவிப்புகளைப் பார்க்கவும் மொபைல், மெசேஜ், தொடர்புகள், கேலெண்டர் ஆகியவற்றை அணுகவும் <xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸுக்கு அனுமதி வழங்கப்படும்."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"உங்கள் அறிவிப்புகளைப் பார்க்கவும் மொபைல், மெசேஜ், தொடர்புகள், கேலெண்டர் ஆகியவற்றை அணுகவும் <xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸுக்கு அனுமதி வழங்கப்படும்."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"ஆப்ஸை ஸ்ட்ரீம் செய்ய <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ஆப்ஸை அனுமதிக்கவா?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"இணைக்கப்பட்டிருக்கும்போது இந்த மொபைலில் நிறுவப்பட்டிருக்கும் ஆப்ஸை அணுகுவதற்கான தொலைநிலை அணுகலை <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> சாதனத்திற்கு வழங்க <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ஆப்ஸை அனுமதிக்கும்."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"இணைக்கப்பட்டிருக்கும்போது இந்த டேப்லெட்டில் நிறுவப்பட்டிருக்கும் ஆப்ஸை அணுகுவதற்கான தொலைநிலை அணுகலை <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> சாதனத்திற்கு வழங்க <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ஆப்ஸை அனுமதிக்கும்."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"இணைக்கப்பட்டிருக்கும்போது இந்தச் சாதனத்தில் நிறுவப்பட்டிருக்கும் ஆப்ஸை அணுகுவதற்கான தொலைநிலை அணுகலை <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> சாதனத்திற்கு வழங்க <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ஆப்ஸை அனுமதிக்கும்."</string> + <string name="permission_apps" msgid="6142133265286656158">"ஆப்ஸ்"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"உங்கள் மொபைலின் ஆப்ஸை ஸ்ட்ரீம் செய்யலாம்"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"மொபைலில் உள்ள இந்தத் தகவல்களை அணுக, <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ஆப்ஸை அனுமதிக்கவும்"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"பன்முக சாதன சேவைகள்"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"உங்கள் மொபைலில் உள்ள படங்கள், மீடியா, அறிவிப்புகள் ஆகியவற்றை அணுக உங்கள் <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> சார்பாக <xliff:g id="APP_NAME">%1$s</xliff:g> அனுமதி கோருகிறது"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"உங்கள் மொபைலிலிருந்து இந்தத் தகவலை அணுக <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ஆப்ஸை அனுமதியுங்கள்"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"அறிவிப்புகள்"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"தொடர்புகள், மெசேஜ்கள், படங்கள் போன்ற தகவல்கள் உட்பட அனைத்து அறிவிப்புகளையும் படிக்க முடியும்"</string> + <string name="permission_storage" msgid="6831099350839392343">"படங்கள் மற்றும் மீடியா"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play சேவைகள்"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"உங்கள் சாதனங்களுக்கு இடையே ஆப்ஸை ஸ்ட்ரீம் செய்ய உங்கள் <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> சார்பாக <xliff:g id="APP_NAME">%1$s</xliff:g> அனுமதி கோருகிறது"</string> <string name="profile_name_generic" msgid="6851028682723034988">"சாதனம்"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"அனுமதி"</string> <string name="consent_no" msgid="2640796915611404382">"அனுமதிக்க வேண்டாம்"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"ஆப்ஸ் அனுமதிகளை உங்கள் வாட்ச்சிற்கு மாற்றுதல்"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"உங்கள் வாட்ச் அமைவை எளிதாக்க, உங்கள் மொபைலில் வழங்கியுள்ள அனுமதிகளையே அமைவின்போது வாட்ச்சில் நிறுவப்பட்ட ஆப்ஸும் பயன்படுத்தும்.\n\n உங்கள் வாட்ச்சிலுள்ள மைக்ரோஃபோன், இருப்பிடம் ஆகியவற்றுக்கான அணுகலும் இந்த அனுமதிகளில் அடங்கக்கூடும்."</string> + <string name="consent_back" msgid="2560683030046918882">"பின்செல்"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> சாதனத்தில் இருக்கும் அதே அனுமதிகளை <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> சாதனத்தில் உள்ள ஆப்ஸுக்கும் வழங்கவா?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p><strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p> சாதனத்தில் உள்ள மைக்ரோஃபோன், கேமரா, இருப்பிட அணுகல், பாதுகாக்கவேண்டிய பிற தகவல்கள் ஆகியவற்றுக்கான அனுமதிகள் இதிலடங்கும்.<strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p> சாதனத்தில் உள்ள அமைப்புகளில் இந்த அனுமதிகளை எப்போது வேண்டுமானாலும் நீங்கள் மாற்றிக்கொள்ளலாம்."</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-te/strings.xml b/packages/CompanionDeviceManager/res/values-te/strings.xml index 73cf3e88e180..6ce530b3392d 100644 --- a/packages/CompanionDeviceManager/res/values-te/strings.xml +++ b/packages/CompanionDeviceManager/res/values-te/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> ద్వారా మేనేజ్ చేయబడటానికి ఒక <xliff:g id="PROFILE_NAME">%1$s</xliff:g>ను ఎంచుకోండి"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"మీ నోటిఫికేషన్లతో ఇంటరాక్ట్ అవ్వడానికి ఇంకా మీ ఫోన్, SMS, కాంటాక్ట్లు, Calendar అనుమతులను యాక్సెస్ చేయడానికి <xliff:g id="APP_NAME">%1$s</xliff:g> అనుమతించబడుతుంది."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"మీ నోటిఫికేషన్లతో ఇంటరాక్ట్ అవ్వడానికి ఇంకా మీ ఫోన్, SMS, కాంటాక్ట్లు, Calendar అనుమతులను యాక్సెస్ చేయడానికి <xliff:g id="APP_NAME">%1$s</xliff:g> అనుమతించబడుతుంది."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"యాప్లను స్ట్రీమ్ చేయడానికి <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ను అనుమతించాలా?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"కనెక్ట్ అయినప్పుడు ఈ ఫోన్లో ఇన్స్టాల్ చేయబడిన యాప్లను యాక్సెస్ చేయడానికి <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> రిమోట్ యాక్సెస్ను అందించడానికి <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ను అనుమతించండి."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"కనెక్ట్ అయినప్పుడు ఈ టాబ్లెట్లో ఇన్స్టాల్ చేయబడిన యాప్లను యాక్సెస్ చేయడానికి <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> రిమోట్ యాక్సెస్ను అందించడానికి <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ను అనుమతించండి."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"కనెక్ట్ అయినప్పుడు ఈ పరికరంలో ఇన్స్టాల్ చేయబడిన యాప్లను యాక్సెస్ చేయడానికి <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> రిమోట్ యాక్సెస్ను అందించడానికి <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ను అనుమతించండి."</string> + <string name="permission_apps" msgid="6142133265286656158">"యాప్లు"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"మీ ఫోన్ యాప్లను స్ట్రీమ్ చేయండి"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"మీ ఫోన్ నుండి ఈ సమాచారాన్ని యాక్సెస్ చేయడానికి <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> యాప్ను అనుమతించండి"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"క్రాస్-డివైజ్ సర్వీసులు"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> మీ ఫోన్ ఫోటోలు, మీడియా, నోటిఫికేషన్లను యాక్సెస్ చేయడానికి మీ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> తరపున అనుమతిని రిక్వెస్ట్ చేస్తోంది"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"మీ ఫోన్ నుండి ఈ సమాచారాన్ని యాక్సెస్ చేయడానికి <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> యాప్ను అనుమతించండి"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"నోటిఫికేషన్లు"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"కాంటాక్ట్లు, మెసేజ్లు, ఫోటోల వంటి సమాచారంతో సహా అన్ని నోటిఫికేషన్లను చదవగలరు"</string> + <string name="permission_storage" msgid="6831099350839392343">"ఫోటోలు, మీడియా"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play సర్వీసులు"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"మీ పరికరాల మధ్య యాప్లను స్ట్రీమ్ చేయడానికి <xliff:g id="APP_NAME">%1$s</xliff:g> మీ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> తరపున అనుమతిని రిక్వెస్ట్ చేస్తోంది"</string> <string name="profile_name_generic" msgid="6851028682723034988">"పరికరం"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"అనుమతించు"</string> <string name="consent_no" msgid="2640796915611404382">"అనుమతించవద్దు"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"మీ వాచ్కు యాప్ అనుమతులను బదిలీ చేయండి"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"మీ వాచ్ను సెటప్ చేయడాన్ని సులభతరం చేయడానికి, సెటప్ సమయంలో మీ వాచ్లో ఇన్స్టాల్ చేయబడిన యాప్లు మీ ఫోన్లో యాప్లకు ఉన్న అవే అనుమతులను ఉపయోగిస్తాయి.\n\n ఈ అనుమతులతో మీ వాచ్ మైక్రోఫోన్, అలాగే లొకేషన్ కూడా ఉండవచ్చు."</string> + <string name="consent_back" msgid="2560683030046918882">"వెనుకకు"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong>లోని యాప్లకు <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>లో ఉన్న అనుమతులను ఇవ్వాలా?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p><strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>లో మైక్రోఫోన్, కెమెరా, లొకేషన్ యాక్సెస్, ఇంకా ఇతర గోప్యమైన సమాచార యాక్సెస్ అనుమతులు ఇందులో ఉండవచ్చు.</p> <p>మీరు <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>లో మీ సెట్టింగ్లలో ఎప్పుడైనా ఈ అనుమతులను మార్చవచ్చు.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-th/strings.xml b/packages/CompanionDeviceManager/res/values-th/strings.xml index 6f29346debc5..aa655a938fea 100644 --- a/packages/CompanionDeviceManager/res/values-th/strings.xml +++ b/packages/CompanionDeviceManager/res/values-th/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"เลือก<xliff:g id="PROFILE_NAME">%1$s</xliff:g>ที่จะให้มีการจัดการโดย <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> จะได้รับอนุญาตให้โต้ตอบกับการแจ้งเตือนและได้รับสิทธิ์เข้าถึงโทรศัพท์, SMS, รายชื่อติดต่อ และปฏิทิน"</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> จะได้รับอนุญาตให้โต้ตอบกับการแจ้งเตือนและได้รับสิทธิ์เข้าถึงโทรศัพท์, SMS, รายชื่อติดต่อ และปฏิทิน"</string> - <string name="title_app_streaming" msgid="4459136600249308574">"อนุญาตให้ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> สตรีมแอปพลิเคชันใช่ไหม"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"อนุญาตให้ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> มอบสิทธิ์เข้าถึงแอปพลิเคชันที่ติดตั้งในโทรศัพท์เครื่องนี้จากระยะไกลให้แก่ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> เมื่อมีการเชื่อมต่อ"</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"อนุญาตให้ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> มอบสิทธิ์เข้าถึงแอปพลิเคชันที่ติดตั้งในแท็บเล็ตเครื่องนี้จากระยะไกลให้แก่ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> เมื่อมีการเชื่อมต่อ"</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"อนุญาตให้ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> มอบสิทธิ์เข้าถึงแอปพลิเคชันที่ติดตั้งในอุปกรณ์เครื่องนี้จากระยะไกลให้แก่ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> เมื่อมีการเชื่อมต่อ"</string> + <string name="permission_apps" msgid="6142133265286656158">"แอป"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"สตรีมแอปของโทรศัพท์คุณ"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"อนุญาตให้ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> เข้าถึงข้อมูลนี้จากโทรศัพท์ของคุณ"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"บริการหลายอุปกรณ์"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> กำลังขอสิทธิ์ในนามของ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> เพื่อเข้าถึงรูปภาพ สื่อ และการแจ้งเตือนในโทรศัพท์ของคุณ"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"อนุญาตให้ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> เข้าถึงข้อมูลนี้จากโทรศัพท์ของคุณ"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"การแจ้งเตือน"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"สามารถอ่านการแจ้งเตือนทั้งหมด รวมถึงข้อมูลอย่างรายชื่อติดต่อ ข้อความ และรูปภาพ"</string> + <string name="permission_storage" msgid="6831099350839392343">"รูปภาพและสื่อ"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"บริการ Google Play"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> กำลังขอสิทธิ์ในนามของ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> เพื่อสตรีมแอประหว่างอุปกรณ์ต่างๆ ของคุณ"</string> <string name="profile_name_generic" msgid="6851028682723034988">"อุปกรณ์"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"อนุญาต"</string> <string name="consent_no" msgid="2640796915611404382">"ไม่อนุญาต"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"โอนสิทธิ์ของแอปไปยังนาฬิกา"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"แอปที่ติดตั้งในนาฬิการะหว่างการตั้งค่าจะใช้สิทธิ์เดียวกันกับโทรศัพท์เพื่อให้การตั้งค่านาฬิกาง่ายขึ้น\n\n สิทธิ์เหล่านี้อาจรวมการเข้าถึงไมโครโฟนและตำแหน่งของนาฬิกา"</string> + <string name="consent_back" msgid="2560683030046918882">"กลับ"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"ให้แอปใน <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> มีสิทธิ์เหมือนกับใน <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> ไหม"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>โดยอาจรวมถึงสิทธิ์เข้าถึงไมโครโฟน กล้อง และตำแหน่ง ตลอดจนสิทธิ์ที่มีความละเอียดอ่อนอื่นๆ ใน <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>คุณเปลี่ยนแปลงสิทธิ์เหล่านี้ได้ทุกเมื่อในการตั้งค่าใน <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-tl/strings.xml b/packages/CompanionDeviceManager/res/values-tl/strings.xml index e557a385dd98..b9ce50b55d8d 100644 --- a/packages/CompanionDeviceManager/res/values-tl/strings.xml +++ b/packages/CompanionDeviceManager/res/values-tl/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Pumili ng <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para pamahalaan ng <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"Papayagan ang <xliff:g id="APP_NAME">%1$s</xliff:g> na makipag-ugnayan sa mga notification mo at ma-access ang iyong mga pahintulot sa Telepono, SMS, Mga Contact, at Kalendaryo."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"Papayagan ang <xliff:g id="APP_NAME">%1$s</xliff:g> na makipag-ugnayan sa mga notification mo at ma-access ang iyong mga pahintulot sa Telepono, SMS, Mga Contact, at Kalendaryo."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Payagan ang <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> na mag-stream ng mga application?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Payagan ang <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> na bigyan ang <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ng malayuang access para ma-access ang mga application na naka-install sa teleponong ito kapag nakakonekta."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Payagan ang <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> na bigyan ang <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ng malayuang access para ma-access ang mga application na naka-install sa tablet na ito kapag nakakonekta."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Payagan ang <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> na bigyan ang <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ng malayuang access para ma-access ang mga application na naka-install sa device na ito kapag nakakonekta."</string> + <string name="permission_apps" msgid="6142133265286656158">"Mga App"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"I-stream ang mga app ng iyong telepono"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Payagan ang <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> na i-access ang impormasyong ito sa iyong telepono"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Mga cross-device na serbisyo"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"Ang <xliff:g id="APP_NAME">%1$s</xliff:g> ay humihiling ng pahintulot sa ngalan ng iyong <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para i-access ang mga larawan, media, at notification ng telepono mo"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Payagan ang <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> na i-access ang impormasyon sa iyong telepono"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Mga Notification"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Magbasa ng lahat ng notification, kabilang ang impormasyon gaya ng mga contact, mensahe, at larawan"</string> + <string name="permission_storage" msgid="6831099350839392343">"Mga larawan at media"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Mga serbisyo ng Google Play"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"Ang <xliff:g id="APP_NAME">%1$s</xliff:g> ay humihiling ng pahintulot sa ngalan ng iyong <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para mag-stream ng mga app sa pagitan ng mga device mo"</string> <string name="profile_name_generic" msgid="6851028682723034988">"device"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Payagan"</string> <string name="consent_no" msgid="2640796915611404382">"Huwag payagan"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Ilipat sa iyong relo ang mga pahintulot sa app"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Para gawing mas madali na i-set up ang iyong relo, gagamitin ng mga app na naka-install sa relo mo sa oras ng pag-set up ang mga pahintulot na ginagamit din sa iyong telepono.\n\n Posibleng kasama sa mga pahintulot na ito ang access sa mikropono at lokasyon ng iyong relo."</string> + <string name="consent_back" msgid="2560683030046918882">"Bumalik"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Bigyan ang mga app sa <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> ng mga pahintulot na mayroon din sa <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Posibleng kabilang dito ang access sa Mikropono, Camera, at Lokasyon, at iba pang pahintulot sa sensitibong impormasyon sa <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Puwede mong baguhin ang mga pahintulot na ito anumang oras sa iyong Mga Setting sa <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-tr/strings.xml b/packages/CompanionDeviceManager/res/values-tr/strings.xml index c75214bf957e..0528086d31f8 100644 --- a/packages/CompanionDeviceManager/res/values-tr/strings.xml +++ b/packages/CompanionDeviceManager/res/values-tr/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> tarafından yönetilecek bir <xliff:g id="PROFILE_NAME">%1$s</xliff:g> seçin"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> adlı uygulamanın bildirimlerinizle etkileşimde bulunup Telefon, SMS, Kişiler ve Takvim izinlerinize erişmesine izin verilir."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> adlı uygulamanın bildirimlerinizle etkileşimde bulunup Telefon, SMS, Kişiler ve Takvim izinlerinize erişmesine izin verilir."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> uygulamasının, uygulamalarda akış gerçekleştirmesine izin verilsin mi?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> uygulamasının, internete bağlanan bu telefondaki yüklü uygulamalara erişebilmesi için <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> adlı cihaza uzaktan erişim izni verin."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> uygulamasının, internete bağlanan bu tabletteki yüklü uygulamalara erişebilmesi için <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> adlı cihaza uzaktan erişim izni verin."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> uygulamasının, internete bağlanan bu cihazdaki yüklü uygulamalara erişebilmesi için <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> adlı cihaza uzaktan erişim izni verin."</string> + <string name="permission_apps" msgid="6142133265286656158">"Uygulamalar"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Telefonunuzun uygulamalarını akışla aktarın"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> uygulamasının, telefonunuzdaki bu bilgilere erişmesine izin verin"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cihazlar arası hizmetler"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g>, telefonunuzdaki fotoğraf, medya ve bildirimlere erişmek için <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> cihazınız adına izin istiyor"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> uygulamasının, telefonunuzdaki bu bilgilere erişmesine izin verin"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Bildirimler"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Kişiler, mesajlar ve fotoğraflar da dahil olmak üzere tüm bildirimleri okuyabilir"</string> + <string name="permission_storage" msgid="6831099350839392343">"Fotoğraflar ve medya"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play hizmetleri"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g>, cihazlarınız arasında uygulama akışı gerçekleştirmek için <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> cihazınız adına izin istiyor"</string> <string name="profile_name_generic" msgid="6851028682723034988">"cihaz"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"İzin ver"</string> <string name="consent_no" msgid="2640796915611404382">"İzin verme"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Uygulama izinlerini saatinize aktarma"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Kurulum sırasında saatinize yüklenen uygulamalar, saat kurulumunuzu kolaylaştırmak için telefonunuzla aynı izinleri kullanır.\n\n Saatinizin mikrofonuna ve konumuna erişim bu izinlere dahil olabilir."</string> + <string name="consent_back" msgid="2560683030046918882">"Geri"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> cihazındaki uygulamalara, <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> cihazındakiyle aynı izinler verilsin mi?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Mikrofon, Kamera ve Konum erişiminin yanı sıra <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> cihazındaki diğer hassas bilgilere erişim izinleri de bu kapsamda olabilir.</p> <p>Bu izinleri istediğiniz zaman <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> cihazındaki Ayarlar bölümünden değiştirebilirsiniz.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-uk/strings.xml b/packages/CompanionDeviceManager/res/values-uk/strings.xml index 46a25b2ba185..ba3d9b5a3ffa 100644 --- a/packages/CompanionDeviceManager/res/values-uk/strings.xml +++ b/packages/CompanionDeviceManager/res/values-uk/strings.xml @@ -22,18 +22,28 @@ <string name="chooser_title" msgid="2262294130493605839">"Виберіть <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, яким керуватиме додаток <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> зможе взаємодіяти з вашими сповіщеннями та отримає дозволи \"Телефон\", \"SMS\", \"Контакти\" й \"Календар\"."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> зможе взаємодіяти з вашими сповіщеннями та отримає дозволи \"Телефон\", \"SMS\", \"Контакти\" й \"Календар\"."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Дозволити додатку <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> транслювати інші додатки?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Дозвольте додатку <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> за наявності з’єднання надавати пристрою <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> віддалений доступ до додатків, установлених на цьому телефоні."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Дозвольте додатку <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> за наявності з’єднання надавати пристрою <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> віддалений доступ до додатків, установлених на цьому планшеті."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Дозвольте додатку <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> за наявності з’єднання надавати пристрою <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> віддалений доступ до додатків, установлених на цьому пристрої."</string> + <string name="permission_apps" msgid="6142133265286656158">"Додатки"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Транслювати додатки телефона"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Надайте додатку <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> доступ до цієї інформації з телефона"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Сервіси для кількох пристроїв"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> від імені вашого пристрою <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> запитує дозвіл на доступ до фотографій, медіафайлів і сповіщень вашого телефона"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Надайте додатку <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> доступ до цієї інформації з телефона"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Сповіщення"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Може читати всі сповіщення, зокрема таку інформацію, як контакти, повідомлення та фотографії"</string> + <string name="permission_storage" msgid="6831099350839392343">"Фотографії та медіафайли"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Сервіси Google Play"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> від імені вашого пристрою <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> запитує дозвіл на трансляцію додатків між вашими пристроями"</string> <string name="profile_name_generic" msgid="6851028682723034988">"пристрій"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Дозволити"</string> <string name="consent_no" msgid="2640796915611404382">"Не дозволяти"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Перенести дозволи для додатків на годинник"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Задля зручності додатки, установлені на годиннику протягом налаштування, використовуватимуть ті самі дозволи, що й на телефоні.\n\n До таких дозволів може належати доступ до мікрофона й геоданих годинника."</string> + <string name="consent_back" msgid="2560683030046918882">"Назад"</string> + <!-- no translation found for permission_sync_confirmation_title (4409622174437248702) --> + <skip /> + <!-- no translation found for permission_sync_summary (4866838188678457084) --> + <skip /> </resources> diff --git a/packages/CompanionDeviceManager/res/values-ur/strings.xml b/packages/CompanionDeviceManager/res/values-ur/strings.xml index c9f930f0f54b..5ca9fd06582d 100644 --- a/packages/CompanionDeviceManager/res/values-ur/strings.xml +++ b/packages/CompanionDeviceManager/res/values-ur/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> کے ذریعے نظم کئے جانے کیلئے <xliff:g id="PROFILE_NAME">%1$s</xliff:g> کو منتخب کریں"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> کو آپ کی اطلاعات کے ساتھ تعامل کرنے اور آپ کے فون، SMS، رابطوں اور کیلنڈر کی اجازتوں تک رسائی کی اجازت ہوگی۔"</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> کو آپ کی اطلاعات کے ساتھ تعامل کرنے اور آپ کے فون، SMS، رابطوں اور کیلنڈر کی اجازتوں تک رسائی کی اجازت ہوگی۔"</string> - <string name="title_app_streaming" msgid="4459136600249308574">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> کو ایپلیکیشنز کی سلسلہ بندی کرنے کی اجازت دیں؟"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"منسلک ہونے پر، اس فون پر انسٹال کردہ ایپلیکیشنز تک رسائی حاصل کرنے کے لیے <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> کو <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> کے لیے ریموٹ تک رسائی فراہم کرنے کی اجازت دیں۔"</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"منسلک ہونے پر، اس ٹیبلیٹ پر انسٹال کردہ ایپلیکیشنز تک رسائی حاصل کرنے کے لیے <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> کو <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> کے لیے ریموٹ تک رسائی فراہم کرنے کی اجازت دیں۔"</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"منسلک ہونے پر، اس آلے پر انسٹال کردہ ایپلیکیشنز تک رسائی حاصل کرنے کے لیے <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> کو <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> کے لیے ریموٹ تک رسائی فراہم کرنے کی اجازت دیں۔"</string> + <string name="permission_apps" msgid="6142133265286656158">"ایپس"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"اپنے فون کی ایپس کی سلسلہ بندی کریں"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> کو اپنے فون سے ان معلومات تک رسائی حاصل کرنے کی اجازت دیں"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"کراس آلے کی سروس"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> ایپ آپ کے <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> کی جانب سے آپ کے فون کی تصاویر، میڈیا اور اطلاعات تک رسائی کی اجازت طلب کر رہی ہے"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"اپنے فون سے اس معلومات تک رسائی حاصل Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> کرنے کی اجازت دیں"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"اطلاعات"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"رابطوں، پیغامات اور تصاویر جیسی معلومات سمیت تمام اطلاعات پڑھ سکتے ہیں"</string> + <string name="permission_storage" msgid="6831099350839392343">"تصاویر اور میڈیا"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play سروسز"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> ایپ آپ کے <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> کی جانب سے آپ کے آلات کے درمیان ایپس کی سلسلہ بندی کرنے کی اجازت کی درخواست کر رہی ہے"</string> <string name="profile_name_generic" msgid="6851028682723034988">"آلہ"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"اجازت دیں"</string> <string name="consent_no" msgid="2640796915611404382">"اجازت نہ دیں"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"اپنی گھڑی پر ایپ کی اجازتیں منتقل کریں"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"آپ کی گھڑی کو سیٹ اپ کرنے کے عمل کو زیادہ آسان بنانے کے لیے، سیٹ اپ کے دوران آپ کی گھڑی پر انسٹال کردہ ایپس انہیں اجازتوں کا استعمال کریں گی جن کا استعمال آپ کا فون کرتا ہے۔\n\n ان اجازتوں میں آپ کی گھڑی کے مائیکروفون اور مقام تک کی رسائی شامل ہو سکتی ہے۔"</string> + <string name="consent_back" msgid="2560683030046918882">"پیچھے"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"ایپس کو ;<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong&gt پر اجازت دیں یکساں اجازتیں جو <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g>;</strong&gt پر کے بطور ہیں؟"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>اس میں مائیکروفون، کیمرا اور مقام تک رسائی اور ;<strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong&gt پر دیگر حساس اجازتیں شامل ہو سکتی ہیں۔</p> <p>آپ <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g>;</strong&gt پر کسی بھی وقت اپنی ترتیبات میں ان اجازتوں کو تبدیل کر سکتے ہیں۔</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-uz/strings.xml b/packages/CompanionDeviceManager/res/values-uz/strings.xml index 91fdd946edf2..f2311fe1a675 100644 --- a/packages/CompanionDeviceManager/res/values-uz/strings.xml +++ b/packages/CompanionDeviceManager/res/values-uz/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> boshqaradigan <xliff:g id="PROFILE_NAME">%1$s</xliff:g> qurilmasini tanlang"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasiga bildirishnomalar bilan ishlash va telefon, SMS, kontaktlar va taqvimga kirishga ruxsat beriladi"</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasiga bildirishnomalar bilan ishlash va telefon, SMS, kontaktlar va taqvimga kirishga ruxsat beriladi"</string> - <string name="title_app_streaming" msgid="4459136600249308574">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ilovasiga ilovalarni strim qilishi uchun ruxsat berilsinmi?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ilovasiga <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ulanganda ushbu telefonda oʻrnatilgan ilovalarga masofadan kirish ruxsatini bering."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ilovasiga <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ulanganda ushbu planshetda oʻrnatilgan ilovalarga masofadan kirish ruxsatini bering."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ilovasiga <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ulanganda ushbu qurilmada oʻrnatilgan ilovalarga masofadan kirish ruxsatini bering."</string> + <string name="permission_apps" msgid="6142133265286656158">"Ilovalar"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Telefondagi ilovalarni translatsiya qilish"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ilovasiga telefondagi ushbu maʼlumot uchun ruxsat bering"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Qurilmalararo xizmatlar"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"Telefoningizdagi rasm, media va bildirishnomalarga kirish uchun <xliff:g id="APP_NAME">%1$s</xliff:g> ilovasi <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> nomidan ruxsat soʻramoqda"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ilovasiga telefondagi ushbu maʼlumot uchun ruxsat bering"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Bildirishnomalar"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Barcha bildirishnomalarni, jumladan, kontaktlar, xabarlar va suratlarni oʻqishi mumkin"</string> + <string name="permission_storage" msgid="6831099350839392343">"Suratlar va media"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play xizmatlari"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"Qurilamalararo ilovalar strimingi uchun <xliff:g id="APP_NAME">%1$s</xliff:g> ilovasi <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> nomidan ruxsat soʻramoqda"</string> <string name="profile_name_generic" msgid="6851028682723034988">"qurilma"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Ruxsat"</string> <string name="consent_no" msgid="2640796915611404382">"Ruxsat berilmasin"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Ilova uchun ruxsatlarni soatingizga uzating"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Soatingizni sozlashni qulaylashtirish maqsadida sozlash paytida soatingizga oʻrnatilgan ilovalar telefoningiz bilan bir xil ruxsatlardan foydalanadi.\n\n Bunday ruxsatlarga soatingiz mikrofoni va joylashuv axborotiga ruxsatlar kirishi mumkin."</string> + <string name="consent_back" msgid="2560683030046918882">"Orqaga"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> ilovalariga <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> qurilmasidagi kabi bir xil ruxsatlar berilsinmi?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Bunga <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> qurilmasidagi Mikrofon, Kamera, Joylashuv kabi muhim ruxsatlar kirishi mumkin.</p> <p>Bu ruxsatlarni istalgan vaqt <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> Sozlamalari orqali oʻzgartirish mumkin.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-vi/strings.xml b/packages/CompanionDeviceManager/res/values-vi/strings.xml index 4f96bd4d7f1a..4ccb9d52a1cf 100644 --- a/packages/CompanionDeviceManager/res/values-vi/strings.xml +++ b/packages/CompanionDeviceManager/res/values-vi/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Chọn một <xliff:g id="PROFILE_NAME">%1$s</xliff:g> sẽ do <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> quản lý"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> sẽ được phép tương tác với thông báo cũng như truy cập vào Điện thoại, SMS, Danh bạ và Lịch."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"<xliff:g id="APP_NAME">%1$s</xliff:g> sẽ được phép tương tác với thông báo cũng như truy cập vào Điện thoại, SMS, Danh bạ và Lịch."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Cho phép <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> truyền trực tuyến ứng dụng?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Cho phép <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> truy cập từ xa vào các ứng dụng đã cài đặt trên <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> khi điện thoại này có kết nối."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Cho phép <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> truy cập từ xa vào các ứng dụng đã cài đặt trên <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> khi máy tính bảng này có kết nối."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Cho phép <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> truy cập từ xa vào các ứng dụng đã cài đặt trên <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> khi thiết bị này có kết nối."</string> + <string name="permission_apps" msgid="6142133265286656158">"Ứng dụng"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Truyền các ứng dụng trên điện thoại của bạn"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Cho phép <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> truy cập vào thông tin này trên điện thoại của bạn"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Dịch vụ trên nhiều thiết bị"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"<xliff:g id="APP_NAME">%1$s</xliff:g> đang yêu cầu quyền thay cho <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> để truy cập vào ảnh, nội dung nghe nhìn và thông báo trên điện thoại của bạn."</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Cho phép <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> truy cập vào thông tin này trên điện thoại của bạn"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Thông báo"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Có thể đọc tất cả các thông báo, kể cả những thông tin như danh bạ, tin nhắn và ảnh"</string> + <string name="permission_storage" msgid="6831099350839392343">"Ảnh và nội dung nghe nhìn"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Dịch vụ Google Play"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> đang yêu cầu quyền thay cho <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> để truyền trực tuyến ứng dụng giữa các thiết bị của bạn"</string> <string name="profile_name_generic" msgid="6851028682723034988">"thiết bị"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Cho phép"</string> <string name="consent_no" msgid="2640796915611404382">"Không cho phép"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Chuyển quyền cho ứng dụng sang đồng hồ"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Để thiết lập đồng hồ dễ dàng hơn, trong quá trình thiết lập, các ứng dụng được cài đặt trên đồng hồ của bạn sẽ sử dụng các quyền giống như trên điện thoại.\n\n Các quyền này có thể bao gồm quyền sử dụng micrô và thông tin vị trí của đồng hồ."</string> + <string name="consent_back" msgid="2560683030046918882">"Quay lại"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Cấp cho các ứng dụng trên <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> các quyền giống như trên <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Những quyền này có thể bao gồm quyền truy cập vào micrô, máy ảnh và thông tin vị trí, cũng như các quyền truy cập thông tin nhạy cảm khác trên <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Bạn có thể thay đổi những quyền này bất cứ lúc nào trong phần Cài đặt trên <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml index 3fdccf229bf8..7697c2f12355 100644 --- a/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml +++ b/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"选择要由<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>管理的<xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”将能与通知互动,并可访问电话、短信、通讯录和日历。"</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”将能与通知互动,并可访问电话、短信、通讯录和日历。"</string> - <string name="title_app_streaming" msgid="4459136600249308574">"是否允许 <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> 流式传输应用?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"在 <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> 连接到网络后,允许 <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> 远程访问该手机上安装的应用。"</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"在 <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> 连接到网络后,允许 <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> 远程访问该平板电脑上安装的应用。"</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"在 <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> 连接到网络后,允许 <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> 远程访问该设备上安装的应用。"</string> + <string name="permission_apps" msgid="6142133265286656158">"应用"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"流式传输手机的应用内容"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"允许“<xliff:g id="APP_NAME">%1$s</xliff:g>”<strong></strong>访问您手机中的这项信息"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"跨设备服务"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”正代表您的<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>请求访问您手机上的照片、媒体内容和通知"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"允许 <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> 访问您手机中的这项信息"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"通知"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"可以读取所有通知,包括合同、消息和照片等信息"</string> + <string name="permission_storage" msgid="6831099350839392343">"照片和媒体内容"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play 服务"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”正代表您的<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>请求在您的设备之间流式传输应用内容"</string> <string name="profile_name_generic" msgid="6851028682723034988">"设备"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"允许"</string> <string name="consent_no" msgid="2640796915611404382">"不允许"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"将应用权限转让给手表"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"为了让您更轻松地设置手表,在设置过程中安装在手表上的应用将使用与手机相同的权限。\n\n这些权限可能包括使用手表的麦克风和位置信息。"</string> + <string name="consent_back" msgid="2560683030046918882">"返回"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"要授予<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong>上的应用与<strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>上相同的权限吗?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>这可能包括<strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>的麦克风、摄像头和位置信息访问权限,以及其他敏感权限。</p> <p>您可以随时在<strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>的“设置”中更改这些权限。</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml index a4dc0c9b6c81..ad0148caab32 100644 --- a/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml +++ b/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"選擇由 <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> 管理的<xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」將可存取通知、電話、短訊、聯絡人和日曆資料。"</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」將可存取通知、電話、短訊、聯絡人和日曆資料。"</string> - <string name="title_app_streaming" msgid="4459136600249308574">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」<strong></strong>串流播放應用程式的內容嗎?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"讓「<xliff:g id="APP_NAME">%1$s</xliff:g>」在「<xliff:g id="DEVICE_NAME">%2$s</xliff:g>」連線時可透過遠端方式存取此手機上安裝的應用程式。"</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"讓「<xliff:g id="APP_NAME">%1$s</xliff:g>」在「<xliff:g id="DEVICE_NAME">%2$s</xliff:g>」連線時可透過遠端方式存取此平板電腦上安裝的應用程式。"</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"讓「<xliff:g id="APP_NAME">%1$s</xliff:g>」在「<xliff:g id="DEVICE_NAME">%2$s</xliff:g>」連線時可透過遠端方式存取此裝置上安裝的應用程式。"</string> + <string name="permission_apps" msgid="6142133265286656158">"應用程式"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"串流播放手機應用程式內容"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」<strong></strong>存取您手機中的這項資料"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"跨裝置服務"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在代表 <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> 要求必要權限,以便存取手機上的相片、媒體和通知"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」<strong></strong>存取您手機中的這項資料"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"通知"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"可以讀取所有通知,包括聯絡人、訊息和電話等資訊"</string> + <string name="permission_storage" msgid="6831099350839392343">"相片和媒體"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play 服務"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在代表 <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> 要求必要權限,以便在裝置之間串流應用程式內容"</string> <string name="profile_name_generic" msgid="6851028682723034988">"裝置"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"允許"</string> <string name="consent_no" msgid="2640796915611404382">"不允許"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"將應用程式權限轉移至手錶"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"為簡化手錶的設定程序,在設定過程中安裝到手錶上的應用程式都將沿用手機上的權限。\n\n這些權限可能包括手錶麥克風和位置的存取權。"</string> + <string name="consent_back" msgid="2560683030046918882">"返回"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"要讓「<xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g>」<strong></strong>的應用程式沿用在「<xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g>」<strong></strong>上的權限嗎?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>這可能包括「<xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g>」<strong></strong>.</p>的麥克風、相機和位置資訊存取權和其他機密權限。</p> <p>你隨時可透過「<xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g>」<strong></strong>的設定變更這些權限。</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml index eec042429ca8..52cc3eeb6276 100644 --- a/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml +++ b/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"選擇要讓「<xliff:g id="APP_NAME">%2$s</xliff:g>」<strong></strong>管理的<xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」將可存取通知、電話、簡訊、聯絡人和日曆資料。"</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」將可存取通知、電話、簡訊、聯絡人和日曆資料。"</string> - <string name="title_app_streaming" msgid="4459136600249308574">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」<strong></strong>串流播放應用程式的內容嗎?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」<strong></strong>在「<xliff:g id="DEVICE_NAME">%2$s</xliff:g>」<strong></strong>連上網際網路時可從遠端存取該手機上安裝的應用程式。"</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」<strong></strong>在「<xliff:g id="DEVICE_NAME">%2$s</xliff:g>」<strong></strong>連上網際網路時可從遠端存取該平板電腦上安裝的應用程式。"</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」<strong></strong>在「<xliff:g id="DEVICE_NAME">%2$s</xliff:g>」<strong></strong>連上網際網路時可從遠端存取該裝置上安裝的應用程式。"</string> + <string name="permission_apps" msgid="6142133265286656158">"應用程式"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"串流傳輸手機應用程式內容"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」<strong></strong>存取手機中的這項資訊"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"跨裝置服務"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在代表你的「<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>」要求必要權限,以便存取手機上的相片、媒體和通知"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」<strong></strong>存取你手機中的這項資訊"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"通知"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"可讀取所有通知,包括聯絡人、訊息和電話等資訊"</string> + <string name="permission_storage" msgid="6831099350839392343">"相片和媒體"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Google Play 服務"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在代表你的「<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>」要求必要權限,以便在裝置之間串流傳輸應用程式內容"</string> <string name="profile_name_generic" msgid="6851028682723034988">"裝置"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"允許"</string> <string name="consent_no" msgid="2640796915611404382">"不允許"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"將應用程式權限轉移到手錶上"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"為簡化手錶的設定程序,只要是在設定過程中安裝到手錶上的應用程式,都將沿用手機上的權限。\n\n 這些權限可能包括手錶的麥克風和位置資訊存取權。"</string> + <string name="consent_back" msgid="2560683030046918882">"返回"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"要讓「<xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g>」<strong></strong>的應用程式沿用在「<xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g>」<strong></strong>上的權限嗎?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>這可能包括「<xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g>」<strong></strong>.</p>的麥克風、相機和位置資訊存取權和其他機密權限。</p> <p>你隨時可透過「<xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g>」<strong></strong>的設定變更這些權限。</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-zu/strings.xml b/packages/CompanionDeviceManager/res/values-zu/strings.xml index be5a195fa5f7..d6779117aca7 100644 --- a/packages/CompanionDeviceManager/res/values-zu/strings.xml +++ b/packages/CompanionDeviceManager/res/values-zu/strings.xml @@ -22,18 +22,26 @@ <string name="chooser_title" msgid="2262294130493605839">"Khetha i-<xliff:g id="PROFILE_NAME">%1$s</xliff:g> ezophathwa yi-<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" product="default" msgid="7113724443198337683">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> izovunyelwa ukuxhumana nezaziso zakho futhi ifinyelele izimvume Zefoni yakho, -SMS, Abathintwayo kanye Nekhalenda."</string> <string name="summary_watch" product="tablet" msgid="7113724443198337683">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> izovunyelwa ukuxhumana nezaziso zakho futhi ifinyelele izimvume Zefoni yakho, -SMS, Abathintwayo kanye Nekhalenda."</string> - <string name="title_app_streaming" msgid="4459136600249308574">"Vumela <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ukusakaza ama-applications?"</string> - <string name="summary_app_streaming" product="default" msgid="6105916810614498138">"Vumela <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ukunikezela <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ngokufinyelela kwerimothi kuma-applications afakiwe kule foni uma ixhunyiwe."</string> - <string name="summary_app_streaming" product="tablet" msgid="2996373715966272792">"Vumela <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ukunikezela <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ngokufinyelela kwerimothi kuma-applications afakiwe kule thebhulethi uma ixhunyiwe."</string> - <string name="summary_app_streaming" product="device" msgid="7614171699434639963">"Vumela <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ukunikezela <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ngokufinyelela kwerimothi kuma-applications afakiwe kule divayisi uma ixhunyiwe."</string> + <string name="permission_apps" msgid="6142133265286656158">"Ama-app"</string> + <string name="permission_apps_summary" msgid="798718816711515431">"Sakaza ama-app wefoni yakho"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Vumela i-<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ifinyelele lolu lwazi kusukela efonini yakho"</string> + <string name="helper_title_app_streaming" msgid="4151687003439969765">"Amasevisi amadivayisi amaningi"</string> + <string name="helper_summary_app_streaming" msgid="7380294597268573523">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> icela imvume esikhundleni se-<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> yakho ukuze ifinyelele izithombe zefoni yakho, imidiya nezaziso"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4693714143506569253">"Vumela <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ukufinyelela lolu lwazi kusuka efonini yakho"</string> <string name="summary_computer" msgid="3798467601598297062"></string> + <string name="permission_notification" msgid="693762568127741203">"Izaziso"</string> + <string name="permission_notification_summary" msgid="884075314530071011">"Ingafunda zonke izaziso, okubandakanya ulwazi olufana noxhumana nabo, imilayezo, nezithombe"</string> + <string name="permission_storage" msgid="6831099350839392343">"Izithombe nemidiya"</string> + <string name="permission_storage_summary" msgid="3918240895519506417"></string> + <string name="helper_title_computer" msgid="4671071173916176037">"Amasevisi we-Google Play"</string> + <string name="helper_summary_computer" msgid="1676407599909474428">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> icela imvume esikhundleni se-<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> yakho ukuze isakaze-bukhoma ama-app phakathi kwamadivayisi akho"</string> <string name="profile_name_generic" msgid="6851028682723034988">"idivayisi"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"Vumela"</string> <string name="consent_no" msgid="2640796915611404382">"Ungavumeli"</string> - <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Dlulisela izimvume ze-app ewashini lakho"</string> - <string name="permission_sync_summary" msgid="8873391306499120778">"Ukuze wenze kube lula ukusetha iwashi lakho, ama-app afakwe ewashini lakho phakathi nokusetha azosebenzisa izimvume ezifanayo nezefoni yakho.\n\n Lezi zimvume zingabandakanya ukufinyelela kumakrofoni nendawo yewashi lakho."</string> + <string name="consent_back" msgid="2560683030046918882">"Emuva"</string> + <string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Nikeza ama-app <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> izimvume ezifanayot <strong>njengaku-<xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string> + <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Lokhu kungase kuhlanganisa Imakrofoni, Ikhamera, kanye Nokufinyelela kwendawo, kanye nezinye izimvume ezibucayi <strong>ku-<xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Ungashintsha lezi zimvume nganoma yisiphi isikhathi Kumasethingi akho <strong>ku-<xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values/strings.xml b/packages/CompanionDeviceManager/res/values/strings.xml index 586a0223b460..fca9ab9a42e8 100644 --- a/packages/CompanionDeviceManager/res/values/strings.xml +++ b/packages/CompanionDeviceManager/res/values/strings.xml @@ -107,13 +107,11 @@ <string name="consent_back">Back</string> <!-- ================== System data transfer ==================== --> - <!-- Title of the permission sync confirmation dialog. [CHAR LIMIT=60] --> - <string name="permission_sync_confirmation_title">Transfer app permissions to your - watch</string> - - <!-- Text of the permission sync explanation in the confirmation dialog. [CHAR LIMIT=400] --> - <string name="permission_sync_summary">To make it easier to set up your watch, - apps installed on your watch during setup will use the same permissions as your phone.\n\n - These permissions may include access to your watch\u2019s microphone and location.</string> + <!-- Title of the permission sync confirmation dialog. [CHAR LIMIT=NONE] --> + <string name="permission_sync_confirmation_title">Give apps on <strong><xliff:g id="companion_device_name" example="Galaxy Watch 5">%1$s</xliff:g></strong> the same permissions as on <strong><xliff:g id="primary_device_name" example="Pixel 6">%2$s</xliff:g></strong>?</string> + + <!-- Text of the permission sync explanation in the confirmation dialog. [CHAR LIMIT=NONE] --> + <string name="permission_sync_summary"><p>This may include Microphone, Camera, and Location access, and other sensitive permissions on <strong><xliff:g id="companion_device_name" example="Galaxy Watch 5">%1$s</xliff:g></strong>.</p> + <p>You can change these permissions any time in your Settings on <strong><xliff:g id="companion_device_name" example="Galaxy Watch 5">%1$s</xliff:g></strong>.</p></string> </resources> diff --git a/packages/CompanionDeviceManager/res/values/styles.xml b/packages/CompanionDeviceManager/res/values/styles.xml index c38323f5f73c..809e98e13b60 100644 --- a/packages/CompanionDeviceManager/res/values/styles.xml +++ b/packages/CompanionDeviceManager/res/values/styles.xml @@ -49,7 +49,6 @@ <style name="DescriptionSummary"> <item name="android:layout_width">match_parent</item> <item name="android:layout_height">wrap_content</item> - <item name="android:gravity">center</item> <item name="android:layout_marginTop">18dp</item> <item name="android:layout_marginLeft">18dp</item> <item name="android:layout_marginRight">18dp</item> diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java index 37cbf3017f0b..e71c945f6327 100644 --- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java +++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java @@ -307,6 +307,7 @@ public class CompanionDeviceActivity extends FragmentActivity implements private void onUserSelectedDevice(@NonNull DeviceFilterPair<?> selectedDevice) { final MacAddress macAddress = selectedDevice.getMacAddress(); + mRequest.setDisplayName(selectedDevice.getDisplayName()); onAssociationApproved(macAddress); } @@ -486,6 +487,7 @@ public class CompanionDeviceActivity extends FragmentActivity implements mSelectedDevice = requireNonNull(deviceFilterPairs.get(0)); final String deviceName = mSelectedDevice.getDisplayName(); + mRequest.setDisplayName(deviceName); final Spanned title = getHtmlFromResources( this, R.string.confirmation_title, appLabel, deviceName); final Spanned summary; diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDataTransferActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDataTransferActivity.java index 67efa03b645f..93040b58d74b 100644 --- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDataTransferActivity.java +++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDataTransferActivity.java @@ -16,20 +16,22 @@ package com.android.companiondevicemanager; +import static android.companion.datatransfer.SystemDataTransferRequest.DATA_TYPE_PERMISSION_SYNC; import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; +import static com.android.companiondevicemanager.Utils.getHtmlFromResources; + import static java.util.Objects.requireNonNull; import android.app.Activity; -import android.companion.SystemDataTransferRequest; +import android.companion.datatransfer.PermissionSyncRequest; +import android.companion.datatransfer.SystemDataTransferRequest; import android.content.Intent; +import android.os.Build; import android.os.Bundle; import android.os.ResultReceiver; -import android.text.Html; import android.util.Log; -import android.view.View; import android.widget.Button; -import android.widget.ListView; import android.widget.TextView; /** @@ -39,14 +41,18 @@ public class CompanionDeviceDataTransferActivity extends Activity { private static final String LOG_TAG = CompanionDeviceDataTransferActivity.class.getSimpleName(); - // UI -> SystemDataTransferProcessor - private static final int RESULT_CODE_SYSTEM_DATA_TRANSFER_ALLOWED = 0; - private static final int RESULT_CODE_SYSTEM_DATA_TRANSFER_DISALLOWED = 1; - private static final String EXTRA_SYSTEM_DATA_TRANSFER_REQUEST = "system_data_transfer_request"; + // Intent data keys from SystemDataTransferProcessor + private static final String EXTRA_PERMISSION_SYNC_REQUEST = "permission_sync_request"; + private static final String EXTRA_COMPANION_DEVICE_NAME = "companion_device_name"; private static final String EXTRA_SYSTEM_DATA_TRANSFER_RESULT_RECEIVER = "system_data_transfer_result_receiver"; + // Intent data keys to SystemDataTransferProcessor + private static final int RESULT_CODE_SYSTEM_DATA_TRANSFER_ALLOWED = 0; + private static final int RESULT_CODE_SYSTEM_DATA_TRANSFER_DISALLOWED = 1; + private SystemDataTransferRequest mRequest; + private CharSequence mCompanionDeviceName; private ResultReceiver mCdmServiceReceiver; @Override @@ -61,23 +67,27 @@ public class CompanionDeviceDataTransferActivity extends Activity { TextView titleView = findViewById(R.id.title); TextView summaryView = findViewById(R.id.summary); - ListView listView = findViewById(R.id.device_list); - listView.setVisibility(View.GONE); Button allowButton = findViewById(R.id.btn_positive); Button disallowButton = findViewById(R.id.btn_negative); final Intent intent = getIntent(); - mRequest = intent.getParcelableExtra(EXTRA_SYSTEM_DATA_TRANSFER_REQUEST); - mCdmServiceReceiver = intent.getParcelableExtra(EXTRA_SYSTEM_DATA_TRANSFER_RESULT_RECEIVER); + mRequest = intent.getParcelableExtra(EXTRA_PERMISSION_SYNC_REQUEST, + PermissionSyncRequest.class); + mCompanionDeviceName = intent.getCharSequenceExtra(EXTRA_COMPANION_DEVICE_NAME); + mCdmServiceReceiver = intent.getParcelableExtra(EXTRA_SYSTEM_DATA_TRANSFER_RESULT_RECEIVER, + ResultReceiver.class); requireNonNull(mRequest); requireNonNull(mCdmServiceReceiver); - if (mRequest.isPermissionSyncAllPackages() - || !mRequest.getPermissionSyncPackages().isEmpty()) { - titleView.setText(Html.fromHtml(getString( - R.string.permission_sync_confirmation_title), 0)); - summaryView.setText(getString(R.string.permission_sync_summary)); + final String primaryDeviceName = Build.MODEL; + + if (mRequest.getDataType() == DATA_TYPE_PERMISSION_SYNC) { + titleView.setText(getHtmlFromResources(this, + R.string.permission_sync_confirmation_title, mCompanionDeviceName, + primaryDeviceName)); + summaryView.setText(getHtmlFromResources(this, R.string.permission_sync_summary, + mCompanionDeviceName)); allowButton.setOnClickListener(v -> allow()); disallowButton.setOnClickListener(v -> disallow()); } @@ -101,7 +111,9 @@ public class CompanionDeviceDataTransferActivity extends Activity { private void sendDataToReceiver(int cdmResultCode) { Bundle data = new Bundle(); - data.putParcelable(EXTRA_SYSTEM_DATA_TRANSFER_REQUEST, mRequest); + if (mRequest instanceof PermissionSyncRequest) { + data.putParcelable(EXTRA_PERMISSION_SYNC_REQUEST, (PermissionSyncRequest) mRequest); + } mCdmServiceReceiver.send(cdmResultCode, data); } diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml index 378e1bb18f52..9f5cf35db62a 100644 --- a/packages/SettingsLib/res/values-af/strings.xml +++ b/packages/SettingsLib/res/values-af/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Stel terug"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Verwyder"</string> <string name="guest_resetting" msgid="7822120170191509566">"Stel tans gassessie terug …"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Stel gastesessie terug?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Dit sal ’n nuwe gastesessie begin en alle programme en data van die huidige sessie uitvee"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Verlaat gasmodus?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Dit sal programme en data in die huidige gastesessie uitvee"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Gaan uit"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Stoor gasaktiwiteit?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Jy kan aktiwiteit in die huidige sessie stoor of alle programme en data uitvee"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Vee uit"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Stoor"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Verlaat gasmodus"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Stel jou gastesessie terug"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Verlaat gasmodus"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Alle aktiwiteit sal uitgevee word wanneer jy uitgaan"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Jy kan jou aktiwiteit stoor of uitvee wanneer jy uitgaan"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Stel terug om sessie-aktiwiteit nou uit te vee, of jy kan aktiwiteit stoor of uitvee wanneer jy uitgaan"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Neem \'n foto"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Kies \'n prent"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Kies foto"</string> diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml index 6d833f97764a..747a935fa740 100644 --- a/packages/SettingsLib/res/values-am/strings.xml +++ b/packages/SettingsLib/res/values-am/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"ዳግም አስጀምር"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"አስወግድ"</string> <string name="guest_resetting" msgid="7822120170191509566">"እንግዳን ዳግም በማስጀመር ላይ…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"የእንግዳ ክፍለ-ጊዜ ዳግም ይጀመር?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"ይህ አዲስ የእንግዳ ክፍለ-ጊዜ ይጀምራል እና ሁሉንም መተግበሪያዎች እና ውሂብ አሁን ካለው ክፍለ-ጊዜ ይሰርዛል"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"ከእንግዳ ሁኔታ ይውጣ?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"ይህ አሁን ካለው የእንግዳ ክፍለ-ጊዜ መተግበሪያዎችን እና ውሂብን ይሰርዛል"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"ውጣ"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"የእንግዳ እንቅስቃሴ ይቀመጥ?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"እንቅስቃሴን አሁን ካለው ክፍለ-ጊዜ ማስቀመጥ ወይም ሁሉንም መተግበሪያዎች እና ውሂብ መሰረዝ ይችላሉ"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"ሰርዝ"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"አስቀምጥ"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"ከእንግዳ ሁኔታ ውጣ"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"የእንግዳ ክፍለ-ጊዜን ዳግም አስጀምር"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"እንግዳ ያስወጡ"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"በሚወጡበት ጊዜ ሁሉም እንቅስቃሴዎች ይሰረዛሉ"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"በሚወጡበት ጊዜ እንቅስቃሴዎን ማስቀመጥ ወይም መሰረዝ ይችላሉ"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"የክፍለ-ጊዜ እንቅስቃሴን አሁን ለመሰረዝ ዳግም ያስጀምሩ፣ ወይም በሚወጡበት ጊዜ እንቅስቃሴን ማስቀመጥ ወይም መሰረዝ ይችላሉ"</string> <string name="user_image_take_photo" msgid="467512954561638530">"ፎቶ አንሳ"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"ምስል ይምረጡ"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"ፎቶ ይምረጡ"</string> diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml index a3c4ac59d314..f9585ad106a7 100644 --- a/packages/SettingsLib/res/values-ar/strings.xml +++ b/packages/SettingsLib/res/values-ar/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"إعادة الضبط"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"إزالة"</string> <string name="guest_resetting" msgid="7822120170191509566">"جارٍ إعادة ضبط جلسة الضيف…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"هل تريد إعادة ضبط جلسة الضيف؟"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"سيؤدي إجراء إعادة الضبط إلى بدء جلسة ضيف جديدة وحذف جميع التطبيقات والبيانات من الجلسة الحالية."</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"هل تريد الخروج من وضع الضيف؟"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"سيؤدي الخروج من وضع الضيف إلى حذف التطبيقات والبيانات من جلسة الضيف الحالية."</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"خروج"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"هل تريد حفظ النشاط في وضع الضيف؟"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"يمكنك حفظ نشاط من الجلسة الحالية أو حذف كلّ التطبيقات والبيانات."</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"حذف"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"حِفظ"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"الخروج من وضع الضيف"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"إعادة ضبط جلسة الضيف"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"الخروج من وضع الضيف"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"سيتم حذف جميع الأنشطة عند الخروج من وضع الضيف."</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"يمكنك حفظ نشاطك أو حذفه عند الخروج من وضع الضيف."</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"يمكنك إجراء إعادة ضبط لحذف نشاط الجلسة الآن، أو حِفظ النشاط أو حذفه عند الخروج من وضع الضيف."</string> <string name="user_image_take_photo" msgid="467512954561638530">"التقاط صورة"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"اختيار صورة"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"اختيار صورة"</string> diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml index b3bba95f949b..66c6f20fac36 100644 --- a/packages/SettingsLib/res/values-as/strings.xml +++ b/packages/SettingsLib/res/values-as/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"ৰিছেট কৰক"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"আঁতৰাওক"</string> <string name="guest_resetting" msgid="7822120170191509566">"অতিথিৰ ছেশ্বন ৰিছেট কৰি থকা হৈছে…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"অতিথিৰ ছেশ্বন ৰিছেট কৰিবনে?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"এইটোৱে এটা অতিথিৰ ছেশ্বন আৰম্ভ কৰিব আৰু বৰ্তমানৰ ছেশ্বনটোৰ পৰা আটাইবোৰ এপ্ আৰু ডেটা মচিব"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"অতিথি ম’ডৰ পৰা বাহিৰ হ’বনে?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"এইটোৱে বৰ্তমানৰ অতিথিৰ ছেশ্বনটোৰ পৰা এপ্ আৰু ডেটা মচিব"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"বাহিৰ হওক"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"অতিথিৰ কাৰ্যকলাপ ছেভ কৰিবনে?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"আপুনি বৰ্তমানৰ ছেশ্বনটোৰ পৰা কাৰ্যকলাপ ছেভ কৰিব পাৰে অথবা আটাইবোৰ এপ্ আৰু ডেটা মচিব পাৰে"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"মচক"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"ছেভ কৰক"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"অতিথি ম’ডৰ পৰা বাহিৰ হওক"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"অতিথিৰ ছেশ্বন ৰিছেট কৰক"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"অতিথিৰ ছেশ্বনৰ পৰা বাহিৰ হওক"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"বাহিৰ হওঁতে আটাইবোৰ কাৰ্যকলাপ মচা হ’ব"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"আপুনি বাহিৰ হওঁতে নিজৰ কাৰ্যকলাপ ছেভ কৰিব অথবা মচিব পাৰে"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"এতিয়াই ছেশ্বনৰ কাৰ্যকলাপ ৰিছেট কৰক অথবা মচক অথবা আপুনি বাহিৰ হওঁতে কাৰ্যকলাপ ছেভ কৰিব অথবা মচিব পাৰে"</string> <string name="user_image_take_photo" msgid="467512954561638530">"এখন ফট’ তোলক"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"এখন প্ৰতিচ্ছবি বাছনি কৰক"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"ফট’ বাছনি কৰক"</string> diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml index ca78c68c83df..ed7c4b4cd847 100644 --- a/packages/SettingsLib/res/values-az/strings.xml +++ b/packages/SettingsLib/res/values-az/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Sıfırlayın"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Silin"</string> <string name="guest_resetting" msgid="7822120170191509566">"Qonaq məlumatı sıfırlanır…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Qonaq sessiyası sıfırlansın?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Bu, yeni qonaq sessiyası başladacaq və cari sessiyadan bütün tətbiqləri və datanı siləcək"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Qonaq rejimindən çıxılsın?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Bununla cari qonaq sessiyasındakı bütün tətbiqlər və data silinəcək"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Çıxın"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Qonaq fəaliyyəti saxlansın?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Cari sessiyadakı fəaliyyəti saxlaya və ya bütün tətbiq və datanı silə bilərsiniz"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Silin"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Yadda saxlayın"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Qonaq rejimindən çıxın"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Qonaq sessiyasını sıfırlayın"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Qonaq rejimindən çıxın"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Çıxış zamanı bütün fəaliyyətlər silinəcək"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Çıxışda fəaliyyətinizi saxlaya və ya silə bilərsiniz"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Sessiya fəaliyyətini indi silmək üçün sıfırlayın və ya çıxışda fəaliyyəti saxlaya və ya silə bilərsiniz"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Foto çəkin"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Şəkil seçin"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Foto seçin"</string> diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml index 0da57e4e7746..f85d31451f6f 100644 --- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml +++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Resetuj"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Ukloni"</string> <string name="guest_resetting" msgid="7822120170191509566">"Sesija gosta se resetuje…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Želite da resetujete sesiju gosta?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Time ćete pokrenuti novu sesiju gosta i izbrisati sve aplikacije i podatke iz aktuelne sesije"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Izaći ćete iz režima gosta?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Time ćete izbrisati sve aplikacije i podatke iz aktuelne sesije gosta"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Izađi"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Sačuvaćete aktivnosti gosta?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Sačuvajte aktivnosti iz aktuelne sesije ili izbrišite sve aplikacije i podatke"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Izbriši"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Sačuvaj"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Izađi iz režima gosta"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Resetuj sesiju gosta"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Izađi iz režima gosta"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Sve aktivnosti će biti izbrisane pri izlazu"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Možete da sačuvate ili izbrišete aktivnosti pri izlazu"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Resetujete da biste izbrisali aktivnosti sesije odmah ili možete da sačuvate ili izbrišete aktivnosti pri izlazu"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Slikaj"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Odaberi sliku"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Izaberite sliku"</string> diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml index 7c58ee7de9dc..061b1ae92120 100644 --- a/packages/SettingsLib/res/values-be/strings.xml +++ b/packages/SettingsLib/res/values-be/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Скінуць"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Выдаліць"</string> <string name="guest_resetting" msgid="7822120170191509566">"Ідзе скід гасцявога сеанса…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Скінуць гасцявы сеанс?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Будзе запушчаны новы гасцявы сеанс. Усе праграмы і даныя бягучага сеанса будуць выдалены"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Выйсці з гасцявога рэжыму?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Будуць выдалены праграмы і даныя бягучага гасцявога сеанса"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Выйсці"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Захаваць дзеянні госця?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Можна захаваць даныя пра дзеянні ў бягучым сеансе ці выдаліць праграмы і даныя"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Выдаліць"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Захаваць"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Выйсці з гасцявога рэжыму"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Скінуць гасцявы сеанс"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Выйсці з гасцявога рэжыму"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Падчас выхаду будуць выдалены ўсе звесткі пра дзеянні"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Падчас выхаду можна захаваць ці выдаліць звесткі пра дзеянні"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Скіньце налады, каб выдаліць звесткі пра дзеянні падчас сеанса. Таксама можна захаваць ці выдаліць гэтыя звесткі ў час выхаду"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Зрабіць фота"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Выбраць відарыс"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Выбраць фота"</string> diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml index f35ed0e8d0a4..55d67faf3846 100644 --- a/packages/SettingsLib/res/values-bg/strings.xml +++ b/packages/SettingsLib/res/values-bg/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Нулиране"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Премахване"</string> <string name="guest_resetting" msgid="7822120170191509566">"Сесията като гост се нулира…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Да се нулира ли сесията като гост?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Така ще стартирате нова сесия като гост и ще изтриете всички приложения и данни от текущата сесия"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Изход от режима на гост?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Така ще изтриете приложенията и данните от текущата сесия като гост"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Изход"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Активност като гост – запазване?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Можете да запазите активността от сесията или да изтриете всички прил. и данни"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Изтриване"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Запазване"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Изход от режима на гост"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Нулиране на сесията като гост"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Изход от сесията като гост"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Цялата активност ще бъде изтрита при изход"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"При изход можете да запазите активността или да я изтриете"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Нулирайте, за да изтриете активността в сесията сега. Можете също да я запазите или изтриете при изход"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Правене на снимка"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Избиране на изображение"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Избиране на снимката"</string> diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml index 7d4208120491..184120e724d2 100644 --- a/packages/SettingsLib/res/values-bn/strings.xml +++ b/packages/SettingsLib/res/values-bn/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"রিসেট করুন"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"সরান"</string> <string name="guest_resetting" msgid="7822120170191509566">"গেস্ট সেশন রিসেট করা হচ্ছে..."</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"অতিথি সেশন রিসেট করতে চান?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"এটি নতুন অতিথি সেশন চালু করবে এবং বর্তমান সেশন থেকে সব অ্যাপ ও ডেটা মুছে দেবে"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"\'অতিথি মোড\' ছেড়ে বেরিয়ে আসবেন?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"এটি বর্তমান অতিথি সেশন থেকে অ্যাপ ও ডেটা মুছে দেবে"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"বেরিয়ে আসুন"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"অতিথি অ্যাক্টিভিটি সেভ করবেন?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"আপনি বর্তমান সেশন থেকে অ্যাক্টিভিটি সেভ করতে বা সব অ্যাপ ও ডেটা মুছতে পারবেন"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"মুছুন"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"সেভ করুন"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"\'অতিথি মোড\' ছেড়ে বেরিয়ে আসুন"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"অতিথি সেশন রিসেট করুন"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"\'অতিথি মোড\' ছেড়ে বেরিয়ে আসুন"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"ছেড়ে বেরিয়ে যাওয়ার সময় সব অ্যাক্টিভিটি মুছে দেওয়া হবে"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"ছেড়ে বেরিয়ে যাওয়ার সময় আপনি অ্যাক্টিভিটি সেভ করতে পারবেন বা মুছতে পারবেন"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"সেশন অ্যাক্টিভিটি মুছে দিতে এখন রিসেট করুন বা ছেড়ে বেরিয়ে আসার সময় আপনি অ্যাক্টিভিটি সেভ করতে বা মুছতে পারবেন"</string> <string name="user_image_take_photo" msgid="467512954561638530">"ফটো তুলুন"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"একটি ইমেজ বেছে নিন"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"ফটো বেছে নিন"</string> diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml index 93941218546a..c308fa69d6f3 100644 --- a/packages/SettingsLib/res/values-bs/strings.xml +++ b/packages/SettingsLib/res/values-bs/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Poništi"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Ukloni"</string> <string name="guest_resetting" msgid="7822120170191509566">"Poništavanje sesije gosta…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Poništiti sesiju gosta?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Ovim ćete pokrenuti novu sesiju gosta i izbrisati sve aplikacije i podatke iz trenutne sesije"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Napustiti način rada za gosta?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Ovim ćete izbrisati aplikacije i podatke iz trenutne sesije gosta"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Napusti"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Sačuvati aktivnost gosta?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Možete sačuvati aktivnost iz sesije ili izbrisati sve aplikacije i podatke"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Izbriši"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Sačuvaj"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Napusti način rada za gosta"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Poništi sesiju gosta"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Izlazak iz sesije gosta"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Sva aktivnost će biti izbrisana kada napustite sesiju"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Možete sačuvati ili izbrisati svoju aktivnost pri napuštanju"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Poništite da sada izbrišete aktivnost iz sesije ili možete sačuvati ili izbrisati aktivnost pri napuštanju"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Snimite fotografiju"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Odaberite sliku"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Odabir fotografije"</string> diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml index 91dcbc91ab88..8ec8f0fc8032 100644 --- a/packages/SettingsLib/res/values-ca/strings.xml +++ b/packages/SettingsLib/res/values-ca/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Restableix"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Suprimeix"</string> <string name="guest_resetting" msgid="7822120170191509566">"S\'està restablint el convidat…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Vols restablir la sessió de convidat?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Aquesta acció iniciarà una nova sessió de convidat i suprimirà totes les aplicacions i dades de la sessió actual"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Sortir del mode de convidat?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Aquesta acció suprimirà les aplicacions i dades de la sessió de convidat actual"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Surt"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Desar l\'activitat de convidat?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Pots desar l\'activitat de la sessió actual o suprimir totes les apps i dades"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Suprimeix"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Desa"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Surt del mode de convidat"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Restableix la sessió de convidat"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Surt del mode de convidat"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Se suprimirà tota l\'activitat en sortir"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Pots desar o suprimir l\'activitat en sortir"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Restableix per suprimir l\'activitat de la sessió ara. També pots desar o suprimir l\'activitat en sortir."</string> <string name="user_image_take_photo" msgid="467512954561638530">"Fes una foto"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Tria una imatge"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Selecciona una foto"</string> diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml index 7729815c5ff4..17e7ce3a27e6 100644 --- a/packages/SettingsLib/res/values-cs/strings.xml +++ b/packages/SettingsLib/res/values-cs/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Resetovat"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Odstranit"</string> <string name="guest_resetting" msgid="7822120170191509566">"Resetování hosta…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Resetovat relaci hosta?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Tímto zahájíte novou relaci hosta a smažete všechny aplikace a data z aktuální relace"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Ukončit režim hosta?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Tímto smažete aplikace a data z aktuální relace hosta"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Ukončit"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Uložit aktivitu hosta?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Aktivitu z aktuální relace můžete uložit, nebo všechny aplikace a data smazat"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Smazat"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Uložit"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Ukončit režim hosta"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Resetovat relaci hosta"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Ukončit režim hosta"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Veškerá aktivita bude při ukončení smazána"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Aktivitu můžete při ukončení uložit nebo smazat"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Aktivitu relace můžete ihned smazat resetováním, případně ji můžete uložit nebo smazat při ukončení"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Pořídit fotku"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Vybrat obrázek"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Vybrat fotku"</string> diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml index 6f4846ee8755..0ef99e9151fb 100644 --- a/packages/SettingsLib/res/values-da/strings.xml +++ b/packages/SettingsLib/res/values-da/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Nulstil"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Fjern"</string> <string name="guest_resetting" msgid="7822120170191509566">"Nulstiller gæst…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Vil du nulstille gæstesessionen?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Denne handling starter en ny gæstesession og sletter alle apps og data fra den aktuelle session"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Vil du afslutte gæstetilstanden?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Denne handling sletter apps og data fra den aktuelle gæstesession."</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Luk"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Vil du gemme gæsteaktiviteten?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Du kan gemme aktivitet fra den aktuelle session eller slette alle apps og data"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Slet"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Gem"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Afslut gæstetilstanden"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Nulstil gæstesession"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Afslut gæstesession"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Al aktivitet slettes ved afslutning"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Du kan gemme eller slette din aktivitet ved afslutning"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Nulstil for at slette sessionsaktiviteten nu, eller du kan gemme eller slette aktivitet ved afslutning"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Tag et billede"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Vælg et billede"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Vælg billede"</string> diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml index 7d66c837d53b..c94218fec760 100644 --- a/packages/SettingsLib/res/values-de/strings.xml +++ b/packages/SettingsLib/res/values-de/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Zurücksetzen"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Entfernen"</string> <string name="guest_resetting" msgid="7822120170191509566">"Gast wird zurückgesetzt…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Gastsitzung zurücksetzen?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Hierdurch wird eine neue Gastsitzung gestartet und alle Apps und Daten der aktuellen Sitzung werden gelöscht"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Gastmodus beenden?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Hierdurch werden Apps und Daten der aktuellen Gastsitzung gelöscht"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Beenden"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Gastaktivität speichern?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Speichere Aktivitäten der aktuellen Sitzung oder lösche alle Apps und Daten"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Löschen"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Speichern"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Gastmodus beenden"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Gastsitzung zurücksetzen"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Gastmodus beenden"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Beim Beenden werden alle Aktivitäten gelöscht"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Speichere oder lösche deine Aktivitäten beim Beenden"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Zurücksetzen, um jetzt die Sitzungsaktivitäten zu löschen, oder Aktivitäten beim Beenden speichern oder löschen"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Foto machen"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Bild auswählen"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Foto auswählen"</string> diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml index 0f04846856bc..6629ef38ea93 100644 --- a/packages/SettingsLib/res/values-el/strings.xml +++ b/packages/SettingsLib/res/values-el/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Επαναφορά"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Κατάργηση"</string> <string name="guest_resetting" msgid="7822120170191509566">"Επαναφορά επισκέπτη…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Επαναφορά περιόδου σύνδεσης επισκέπτη;"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Με αυτόν τον τρόπο θα ξεκινήσει μια νέα περίοδος σύνδεσης επισκέπτη και θα διαγραφούν όλες οι εφαρμογές και τα δεδομένα από την τρέχουσα περίοδο σύνδεσης"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Έξοδος από λειτουργία επισκέπτη;"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Θα διαγραφούν εφαρμογές και δεδομένα από την τρέχουσα περίοδο σύνδεσης επισκέπτη"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Έξοδος"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Αποθήκευση δραστ. επισκέπτη;"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Αποθήκευση δραστ. τρέχουσας περιόδου σύνδεσης ή διαγραφή εφαρμογών και δεδομένων"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Διαγραφή"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Αποθήκευση"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Έξοδος από λειτουργία επισκέπτη"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Επαναφορά περ. σύνδεσης επισκέπτη"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Έξοδος επισκέπτη"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Όλη η δραστηριότητα θα διαγραφεί κατά την έξοδο"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Αποθηκεύστε ή διαγράψτε τη δραστηριότητά σας κατά την έξοδο"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Κάντε επαναφορά για να διαγράψετε τη δραστηριότητα της περιόδου σύνδεσης τώρα ή μπορείτε να αποθηκεύσετε ή να διαγράψετε τη δραστηριότητα κατά την έξοδο"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Λήψη φωτογραφίας"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Επιλογή εικόνας"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Επιλογή φωτογραφίας"</string> diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml index 74e2dbbd05c9..23121e244477 100644 --- a/packages/SettingsLib/res/values-en-rAU/strings.xml +++ b/packages/SettingsLib/res/values-en-rAU/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Reset"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Remove"</string> <string name="guest_resetting" msgid="7822120170191509566">"Resetting guest…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Reset guest session?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"This will start a new guest session and delete all apps and data from the current session"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Exit guest mode?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"This will delete apps and data from the current guest session"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Exit"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Save guest activity?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"You can save activity from the current session or delete all apps and data"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Delete"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Save"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Exit guest mode"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Reset guest session"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Exit guest"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"All activity will be deleted on exit"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"You can save or delete your activity on exit"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Reset to delete session activity now, or you can save or delete activity on exit"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Take a photo"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Choose an image"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Select photo"</string> diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml index eacaad02883f..5c5b6b9ddc3c 100644 --- a/packages/SettingsLib/res/values-en-rCA/strings.xml +++ b/packages/SettingsLib/res/values-en-rCA/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Reset"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Remove"</string> <string name="guest_resetting" msgid="7822120170191509566">"Resetting guest…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Reset guest session?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"This will start a new guest session and delete all apps and data from the current session"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Exit guest mode?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"This will delete apps and data from the current guest session"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Exit"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Save guest activity?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"You can save activity from the current session or delete all apps and data"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Delete"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Save"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Exit guest mode"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Reset guest session"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Exit guest"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"All activity will be deleted on exit"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"You can save or delete your activity on exit"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Reset to delete session activity now, or you can save or delete activity on exit"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Take a photo"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Choose an image"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Select photo"</string> diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml index 74e2dbbd05c9..23121e244477 100644 --- a/packages/SettingsLib/res/values-en-rGB/strings.xml +++ b/packages/SettingsLib/res/values-en-rGB/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Reset"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Remove"</string> <string name="guest_resetting" msgid="7822120170191509566">"Resetting guest…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Reset guest session?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"This will start a new guest session and delete all apps and data from the current session"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Exit guest mode?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"This will delete apps and data from the current guest session"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Exit"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Save guest activity?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"You can save activity from the current session or delete all apps and data"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Delete"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Save"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Exit guest mode"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Reset guest session"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Exit guest"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"All activity will be deleted on exit"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"You can save or delete your activity on exit"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Reset to delete session activity now, or you can save or delete activity on exit"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Take a photo"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Choose an image"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Select photo"</string> diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml index 74e2dbbd05c9..23121e244477 100644 --- a/packages/SettingsLib/res/values-en-rIN/strings.xml +++ b/packages/SettingsLib/res/values-en-rIN/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Reset"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Remove"</string> <string name="guest_resetting" msgid="7822120170191509566">"Resetting guest…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Reset guest session?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"This will start a new guest session and delete all apps and data from the current session"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Exit guest mode?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"This will delete apps and data from the current guest session"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Exit"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Save guest activity?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"You can save activity from the current session or delete all apps and data"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Delete"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Save"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Exit guest mode"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Reset guest session"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Exit guest"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"All activity will be deleted on exit"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"You can save or delete your activity on exit"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Reset to delete session activity now, or you can save or delete activity on exit"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Take a photo"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Choose an image"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Select photo"</string> diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml index 70227dce71e4..df280cdbbf8a 100644 --- a/packages/SettingsLib/res/values-en-rXC/strings.xml +++ b/packages/SettingsLib/res/values-en-rXC/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Reset"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Remove"</string> <string name="guest_resetting" msgid="7822120170191509566">"Resetting guest…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Reset guest session?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"This will start a new guest session and delete all apps and data from the current session"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Exit guest mode?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"This will delete apps and data from the current guest session"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Exit"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Save guest activity?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"You can save activity from the current session or delete all apps and data"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Delete"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Save"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Exit guest mode"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Reset guest session"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Exit guest"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"All activity will be deleted on exit"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"You can save or delete your activity on exit"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Reset to delete session activity now, or you can save or delete activity on exit"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Take a photo"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Choose an image"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Select photo"</string> diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml index d96e7f07a161..afdfa9242627 100644 --- a/packages/SettingsLib/res/values-es-rUS/strings.xml +++ b/packages/SettingsLib/res/values-es-rUS/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Restablecer"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Quitar"</string> <string name="guest_resetting" msgid="7822120170191509566">"Restableciendo invitado…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"¿Quieres restablecer la sesión de invitado?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Esta acción comenzará una nueva sesión de invitado y borrará todas las apps y los datos de la sesión actual"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"¿Salir del modo de invitado?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Esta acción borrará todas las apps y los datos de la sesión de invitado actual"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Salir"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"¿Guardar actividad de invitado?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Puedes guardar la actividad de la sesión actual o borrar las apps y los datos"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Borrar"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Guardar"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Salir del modo de invitado"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Restablecer la sesión de invitado"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Salir del modo de invitado"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Cuando salgas, se borrará toda la actividad"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Puedes guardar o borrar la actividad cuando salgas"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Restablece la sesión para borrar la actividad ahora, o bien guarda y borra la actividad cuando salgas"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Tomar una foto"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Elegir una imagen"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Seleccionar foto"</string> diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml index f9c6121c2eae..3d5f5198d847 100644 --- a/packages/SettingsLib/res/values-es/strings.xml +++ b/packages/SettingsLib/res/values-es/strings.xml @@ -95,7 +95,7 @@ <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Desconectando…"</string> <string name="bluetooth_connecting" msgid="5871702668260192755">"Estableciendo conexión…"</string> <string name="bluetooth_connected" msgid="8065345572198502293">"Conectado<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> - <string name="bluetooth_pairing" msgid="4269046942588193600">"Vinculando…"</string> + <string name="bluetooth_pairing" msgid="4269046942588193600">"Emparejando…"</string> <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"Conectado a <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (sin audio de teléfono)"</string> <string name="bluetooth_connected_no_a2dp" msgid="8566874395813947092">"Conectado (sin audio multimedia) a <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> <string name="bluetooth_connected_no_map" msgid="3381860077002724689">"Conectado a <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (sin acceso a mensajes)"</string> @@ -570,7 +570,7 @@ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Perfil restringido"</string> <string name="user_add_user_title" msgid="5457079143694924885">"¿Añadir nuevo usuario?"</string> <string name="user_add_user_message_long" msgid="1527434966294733380">"Puedes compartir este dispositivo si creas más usuarios. Cada uno tendrá su propio espacio y podrá personalizarlo con aplicaciones, un fondo de pantalla y mucho más. Los usuarios también pueden ajustar opciones del dispositivo, como la conexión Wi‑Fi, que afectan a todos los usuarios.\n\nCuando añadas un usuario, tendrá que configurar su espacio.\n\nCualquier usuario puede actualizar aplicaciones de todos los usuarios. Es posible que no se transfieran los servicios y opciones de accesibilidad al nuevo usuario."</string> - <string name="user_add_user_message_short" msgid="3295959985795716166">"Al añadir un usuario nuevo, este debe configurar su espacio.\n\nCualquier usuario puede actualizar las aplicaciones del resto de usuarios."</string> + <string name="user_add_user_message_short" msgid="3295959985795716166">"Al añadir un usuario nuevo, debe configurar su espacio.\n\nCualquier usuario puede actualizar las aplicaciones del resto de usuarios."</string> <string name="user_setup_dialog_title" msgid="8037342066381939995">"¿Configurar usuario ahora?"</string> <string name="user_setup_dialog_message" msgid="269931619868102841">"Asegúrate de que la persona está disponible en este momento para usar el dispositivo y configurar su espacio."</string> <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"¿Quieres configurar un perfil ahora?"</string> @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Restablecer"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Quitar"</string> <string name="guest_resetting" msgid="7822120170191509566">"Restableciendo invitado…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"¿Restablecer sesión de invitado?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Se iniciará una nueva sesión de invitado y se borrarán todas las aplicaciones y datos de esta sesión"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"¿Salir del modo invitados?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Se eliminarán todas las aplicaciones y datos de la sesión de invitado"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Salir"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"¿Guardar actividad de invitados?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Puedes guardar la actividad de esta sesión o eliminar las aplicaciones y datos"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Eliminar"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Guardar"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Salir del modo invitados"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Restablecer sesión de invitado"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Salir del modo invitados"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Toda la actividad se eliminará cuando salgas"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Puedes guardar o eliminar tu actividad cuando salgas"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Restablece la sesión para eliminar la actividad ahora, o guarda o elimina la actividad cuando salgas"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Hacer foto"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Seleccionar una imagen"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Seleccionar foto"</string> diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml index 29376f30c1fb..a42fc4d5f6c8 100644 --- a/packages/SettingsLib/res/values-et/strings.xml +++ b/packages/SettingsLib/res/values-et/strings.xml @@ -589,7 +589,7 @@ <string name="add_user_failed" msgid="4809887794313944872">"Uue kasutaja loomine ebaõnnestus"</string> <string name="add_guest_failed" msgid="8074548434469843443">"Uue külalise loomine ei õnnestunud"</string> <string name="user_nickname" msgid="262624187455825083">"Hüüdnimi"</string> - <string name="user_add_user" msgid="7876449291500212468">"Kasutaja lisamine"</string> + <string name="user_add_user" msgid="7876449291500212468">"Lisa kasutaja"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Lisa külaline"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Eemalda külaline"</string> <string name="guest_reset_guest" msgid="6110013010356013758">"Lähtesta külastajaseanss"</string> @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Lähtesta"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Eemalda"</string> <string name="guest_resetting" msgid="7822120170191509566">"Külastajaseansi lähtestamine …"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Kas lähtestada külastajaseanss?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"See alustab uut külastajaseanssi ning kustutab kõik praeguse seansi rakendused ja andmed"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Kas väljuda külalisrežiimist?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"See kustutab praeguse külastajaseansi rakendused ja andmed"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Välju"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Kas salvestada külalise tegevus?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Võite selle seansi tegevused salvestada või kustutada kõik rakendused ja andmed."</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Kustuta"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Salvesta"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Välju külalisrežiimist"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Lähtesta külastajaseanss"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Välju külastajaseansist"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Kõik tegevused kustutatakse väljumisel"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Võite tegevused salvestada või kustutada väljumisel"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Lähtestage, et seansi tegevused kohe kustutada; samuti võite tegevused salvestada või kustutada väljumisel"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Pildistage"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Valige pilt"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Valige foto"</string> diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml index 5386c3513fa4..792536285203 100644 --- a/packages/SettingsLib/res/values-eu/strings.xml +++ b/packages/SettingsLib/res/values-eu/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Berrezarri"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Kendu"</string> <string name="guest_resetting" msgid="7822120170191509566">"Gonbidatuentzako saioa berrezartzen…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Gonbidatuentzako saioa berrezarri nahi duzu?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Gonbidatuentzako saio berri bat abiaraziko da, eta saio honetako aplikazio eta datu guztiak ezabatuko"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Gonbidatu modutik irten nahi duzu?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Gonbidatuentzako saio honetako aplikazioak eta datuak ezabatuko dira"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Irten"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Gonbidatuaren jarduerak gorde nahi dituzu?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Saio honetako jarduerak gorde ditzakezu, edo aplikazio eta datu guztiak ezabatu"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Ezabatu"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Gorde"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Irten gonbidatu modutik"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Berrezarri gonbidatuentzako saioa"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Irten gonbidatu modutik"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Saiotik irtetean, jarduera guztiak ezabatuko dira"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Irtetean, jarduerak gorde edo ezabatu egin ditzakezu"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Berrezarri saioa jarduerak ezabatzeko (bestela, jarduerak gordetzea edo ezabatzea aukera dezakezu irtetean)"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Atera argazki bat"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Aukeratu irudi bat"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Hautatu argazki bat"</string> diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml index 740e1e69906f..34bed451dbeb 100644 --- a/packages/SettingsLib/res/values-fa/strings.xml +++ b/packages/SettingsLib/res/values-fa/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"بازنشانی"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"برداشتن"</string> <string name="guest_resetting" msgid="7822120170191509566">"درحال بازنشانی مهمان…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"جلسه مهمان بازنشانی شود؟"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"با این کار، جلسه مهمان جدیدی شروع خواهد شد و همه برنامهها و دادهها از جلسه کنونی حذف خواهند شد"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"از حالت مهمان خارج میشوید؟"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"با این کار، برنامهها و دادهها از جلسه مهمان کنونی حذف خواهند شد."</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"خروج"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"فعالیت مهمان ذخیره شود؟"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"میتوانید فعالیت جلسه کنونی را ذخیره کنید یا همه برنامه و دادهها را حذف کنید"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"حذف"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"ذخیره"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"خروج از حالت مهمان"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"بازنشاندن جلسه مهمان"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"خروج مهمان"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"همه فعالیتها هنگام خروج حذف خواهد شد"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"میتوانید فعالیتتان را هنگام خروج ذخیره یا حذف کنید"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"برای حذف فعالیت جلسه در این لحظه، بازنشانی کنید یا میتوانید فعالیت را هنگام خروج ذخیره یا حذف کنید"</string> <string name="user_image_take_photo" msgid="467512954561638530">"عکس گرفتن"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"انتخاب تصویر"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"انتخاب عکس"</string> diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml index 32c52412359b..e14cf873faa9 100644 --- a/packages/SettingsLib/res/values-fi/strings.xml +++ b/packages/SettingsLib/res/values-fi/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Nollaa"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Poista"</string> <string name="guest_resetting" msgid="7822120170191509566">"Nollataan vierasta…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Nollataanko vierailija-käyttökerta?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Tämä aloittaa uuden vierailija-käyttökerran ja kaikki nykyisen istunnon sovellukset ja data poistetaan"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Poistutaanko vierastilasta?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Tämä poistaa nykyisen vierailija-käyttökerran sovellukset ja datan"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Sulje"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Tallennetaanko vierastoiminta?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Voit tallentaa tämän istunnon toimintaa tai poistaa kaikki sovellukset ja datan"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Poista"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Tallenna"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Poistu vierastilasta"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Nollaa vierailija-käyttökerta"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Kirjaa vieras ulos"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Kaikki toiminta poistetaan uloskirjaamisen aikana"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Voit tallentaa tai poistaa toiminnan poistuessasi"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Nollaa poistaaksesi istunnon toiminnan nyt, tai voit tallentaa tai poistaa toimintaa poistuessasi"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Ota kuva"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Valitse kuva"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Valitse kuva"</string> diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml index e1e731f601e7..8ca7c42a5385 100644 --- a/packages/SettingsLib/res/values-fr-rCA/strings.xml +++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Réinitialiser"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Retirer"</string> <string name="guest_resetting" msgid="7822120170191509566">"Réinitialisation de la session Invité en cours…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Réinitialiser la session d\'invité?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Une nouvelle session d\'invité sera lancée, et toutes les applications et données de la session en cours seront supprimées"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Quitter le mode Invité?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Les applications et les données de la session d\'invité en cours seront supprimées"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Quitter"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Enregistrer l\'activité d\'invité?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Vous pouvez enregistrer l\'activité de session ou supprimer les applis et données"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Supprimer"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Enregistrer"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Quitter le mode Invité"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Réinitialiser la session d\'invité"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Quitter la session d\'invité"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Toute l\'activité sera supprimée à la fin de la session"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Vous pouvez enregistrer ou supprimer votre activité à la fin"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Réinitialisez pour supprimer l\'activité de la session maintenant, ou vous pouvez enregistrer ou supprimer l\'activité à la fin de la session"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Prendre une photo"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Sélectionner une image"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Sélectionnez une photo"</string> diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml index e635464d0926..265a21f55535 100644 --- a/packages/SettingsLib/res/values-fr/strings.xml +++ b/packages/SettingsLib/res/values-fr/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Réinitialiser"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Supprimer"</string> <string name="guest_resetting" msgid="7822120170191509566">"Réinitialisation de la session Invité…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Réinitialiser la session Invité ?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Cette action lancera une nouvelle session Invité et supprimera toutes les applis et données de la session actuelle"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Quitter le mode Invité ?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Cette action supprimera les applis et données de la session Invité actuelle."</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Quitter"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Enregistrer l\'activité ?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Enregistrez l\'activité de la session actuelle ou supprimez les applis et données"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Supprimer"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Enregistrer"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Quitter le mode Invité"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Réinitialiser la session Invité"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Quitter le mode Invité"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Toute l\'activité sera supprimée une fois la session quittée"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Vous pouvez enregistrer ou supprimer l\'activité en quittant"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Réinitialisez la session pour supprimer immédiatement l\'activité, qui pourra aussi être enregistrée ou supprimée lorsque vous quitterez la session"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Prendre une photo"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Choisir une image"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Sélectionner une photo"</string> diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml index f5ea9d473021..cd002d5f8d7a 100644 --- a/packages/SettingsLib/res/values-gl/strings.xml +++ b/packages/SettingsLib/res/values-gl/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Restablecer"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Quitar"</string> <string name="guest_resetting" msgid="7822120170191509566">"Restablecendo sesión de convidado…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Queres restablecer a sesión de convidado?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Iniciarase unha nova sesión de convidado e eliminaranse todas as aplicacións e datos desta sesión"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Saír do modo de convidado?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Eliminaranse as aplicacións e os datos da sesión de convidado"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Saír"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Gardar actividade do convidado?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Podes gardar a actividade da sesión ou eliminar todas as aplicacións e datos"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Eliminar"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Gardar"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Saír do modo de convidado"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Restablecer sesión de convidado"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Saír do modo de convidado"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Eliminarase toda a actividade ao saír"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Podes gardar ou eliminar a túa actividade ao saír"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Restablece a sesión para eliminar a actividade agora, ou ben gárdaa ou elimínaa ao saír"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Tirar foto"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Escoller imaxe"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Seleccionar foto"</string> diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml index a9c4b69b261a..df53e0212121 100644 --- a/packages/SettingsLib/res/values-gu/strings.xml +++ b/packages/SettingsLib/res/values-gu/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"રીસેટ કરો"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"કાઢી નાખો"</string> <string name="guest_resetting" msgid="7822120170191509566">"અતિથિને રીસેટ કરી રહ્યાં છીએ…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"શું અતિથિ સત્ર રીસેટ કરીએ?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"આમ કરવાથી કોઈ નવું અતિથિ સત્ર ચાલુ થશે તેમજ હાલના સત્રમાંની તમામ ઍપ અને ડેટા ડિલીટ થશે"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"શું અતિથિ મોડમાંથી બહાર નીકળીએ?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"આમ કરવાથી હાલના અતિથિ સત્રની તમામ ઍપ અને ડેટા ડિલીટ કરવામાં આવશે"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"બહાર નીકળો"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"શું અતિથિ પ્રવૃત્તિ સાચવીએ?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"તમે હાલના સત્રની પ્રવૃત્તિ સાચવી શકો છો અથવા તમામ ઍપ અને ડેટા ડિલીટ કરી શકો છો"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"ડિલીટ કરો"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"સાચવો"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"અતિથિ મોડમાંથી બહાર નીકળો"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"અતિથિ સત્ર રીસેટ કરો"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"અતિથિ મોડમાંથી બહાર નીકળો"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"બહાર નીકળતી વખતે તમામ પ્રવૃત્તિ ડિલીટ કરવામાં આવશે"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"બહાર નીકળતી વખતે તમે પ્રવૃત્તિ સાચવી કે ડિલીટ કરી શકશો"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"સત્રની પ્રવૃત્તિ હમણાં ડિલીટ કરવા માટે રીસેટ કરો અથવા બહાર નીકળતી વખતે તમે પ્રવૃત્તિ સાચવી કે ડિલીટ કરી શકશો"</string> <string name="user_image_take_photo" msgid="467512954561638530">"ફોટો લો"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"છબી પસંદ કરો"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"ફોટો પસંદ કરો"</string> diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml index 02b78c16aabc..dfa4623027de 100644 --- a/packages/SettingsLib/res/values-hi/strings.xml +++ b/packages/SettingsLib/res/values-hi/strings.xml @@ -570,7 +570,7 @@ <string name="user_add_profile_item_title" msgid="3111051717414643029">"प्रतिबंधित प्रोफ़ाइल"</string> <string name="user_add_user_title" msgid="5457079143694924885">"नया उपयोगकर्ता जोड़ें?"</string> <string name="user_add_user_message_long" msgid="1527434966294733380">"आप और ज़्यादा उपयोगकर्ता बनाकर इस डिवाइस को दूसरे लोगों के साथ शेयर कर सकते हैं. हर उपयोगकर्ता के पास अपनी जगह होती है, जिसमें वह मनपसंद तरीके से ऐप्लिकेशन, वॉलपेपर और दूसरी चीज़ों में बदलाव कर सकते हैं. उपयोगकर्ता वाई-फ़ाई जैसी डिवाइस सेटिंग में भी बदलाव कर सकते हैं, जिसका असर हर किसी पर पड़ेगा.\n\nजब आप कोई नया उपयोगकर्ता जोड़ते हैं तो उन्हें अपनी जगह सेट करनी होगी.\n\nकोई भी उपयोगकर्ता दूसरे सभी उपयोगकर्ताओं के लिए ऐप्लिकेशन अपडेट कर सकता है. ऐसा भी हो सकता है कि सुलभता सेटिंग और सेवाएं नए उपयोगकर्ता को ट्रांसफ़र न हो पाएं."</string> - <string name="user_add_user_message_short" msgid="3295959985795716166">"जब आप कोई नया उपयोगकर्ता जोड़ते हैं, तो उसे अपनी जगह सेट करनी होती है.\n\nकोई भी उपयोगकर्ता बाकी सभी उपयोगकर्ताओं के लिए ऐप्लिकेशन अपडेट कर सकता है."</string> + <string name="user_add_user_message_short" msgid="3295959985795716166">"कोई नया उपयोगकर्ता जोड़ने पर, उसे अपनी जगह सेट करनी होती है.\n\nकोई भी उपयोगकर्ता बाकी सभी उपयोगकर्ताओं के लिए ऐप्लिकेशन अपडेट कर सकता है."</string> <string name="user_setup_dialog_title" msgid="8037342066381939995">"उपयोगकर्ता को अभी सेट करें?"</string> <string name="user_setup_dialog_message" msgid="269931619868102841">"पक्का करें कि व्यक्ति डिवाइस का इस्तेमाल करने और अपनी जगह सेट करने के लिए मौजूद है"</string> <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"प्रोफ़ाइल अभी सेट करें?"</string> @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"रीसेट करें"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"हटाएं"</string> <string name="guest_resetting" msgid="7822120170191509566">"मेहमान के तौर पर ब्राउज़ करने का सेशन रीसेट किया जा रहा है…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"क्या मेहमान मोड के मौजूदा सेशन को रीसेट करना है?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"ऐसा करने पर, मेहमान के तौर पर ब्राउज़ करने का एक नया सेशन शुरू हो जाएगा. साथ ही, पिछले सेशन में मौजूद डेटा और इस्तेमाल किए जा रहे ऐप्लिकेशन को मिटा दिया जाएगा"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"मेहमान मोड से बाहर निकलना है?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"इससे, मेहमान मोड के मौजूदा सेशन का डेटा और इसमें इस्तेमाल हो रहे ऐप मिट जाएंगे"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"बाहर निकलें"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"मेहमान मोड की गतिविधि को सेव करना है?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"मौजूदा सेशन की गतिविधि को सेव किया जा सकता है या सभी ऐप और डेटा को मिटाया जा सकता है"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"मिटाएं"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"सेव करें"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"मेहमान मोड से बाहर निकलें?"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"मेहमान मोड के सेशन को रीसेट करें?"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"मेहमान मोड से बाहर निकलें"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"बाहर निकलने पर, सारी गतिविधि मिट जाएगी"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"बाहर निकलने पर, गतिविधि को मिटाया या सेव किया जा सकता है"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"सेशन की गतिविधि को अभी मिटाने के लिए, रीसेट करें. इसके अलावा, बाहर निकलने पर, गतिविधि को मिटाया या सेव किया जा सकता है"</string> <string name="user_image_take_photo" msgid="467512954561638530">"फ़ोटो खींचें"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"कोई इमेज चुनें"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"फ़ोटो चुनें"</string> diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml index fdf14b3fab88..994ac1ecce73 100644 --- a/packages/SettingsLib/res/values-hr/strings.xml +++ b/packages/SettingsLib/res/values-hr/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Poništi"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Ukloni"</string> <string name="guest_resetting" msgid="7822120170191509566">"Poništavanje gostujuće sesije…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Želite li poništiti gostujuću sesiju?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Time će se pokrenuti nova gostujuća sesija i izbrisati sve aplikacije i podaci iz trenutačne sesije."</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Napustiti način rada za goste?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Time će se izbrisati aplikacije i podaci iz trenutačne gostujuće sesije."</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Izlaz"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Spremiti aktivnosti gosta?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Možete spremiti aktivnosti iz ove sesije ili izbrisati sve aplikacije i podatke"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Izbriši"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Spremi"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Izlaz iz načina rada za goste"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Poništi gostujuću sesiju"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Izlaz iz gostujuće sesije"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Sve će se aktivnosti izbrisati na izlasku"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Možete spremiti ili izbrisati svoje aktivnosti na izlasku"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Poništite da biste odmah izbrisali aktivnost sesije, a možete i spremiti ili izbrisati aktivnost na izlasku."</string> <string name="user_image_take_photo" msgid="467512954561638530">"Fotografiraj"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Odaberi sliku"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Odabir slike"</string> diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml index 862078055372..fe6bc88cded3 100644 --- a/packages/SettingsLib/res/values-hu/strings.xml +++ b/packages/SettingsLib/res/values-hu/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Visszaállítás"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Eltávolítás"</string> <string name="guest_resetting" msgid="7822120170191509566">"Vendég munkamenet visszaállítása…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Visszaállítja a vendégmunkamenetet?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"A művelettel új vendégmunkamenetet indít, valamint az összes alkalmazást és adatot törli az aktuális munkamenetből"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Kilép a vendég módból?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"A művelettel törlődnek az aktuális vendégmunkamenet alkalmazásai és adatai"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Kilépés"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Menti a vendégtevékenységeket?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Tevékenységeket menthet az aktuális munkamenetből, vagy minden appot és adatot törölhet"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Törlés"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Mentés"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Kilépés a vendég módból"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Vendégmunkamenet visszaállítása"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Vendég kiléptetése"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"A kilépéssel minden tevékenység törlődik"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"A kilépéskor mentheti vagy törölheti a tevékenységeket"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Visszaállítással azonnal törölheti a munkamenethez tartozó tevékenységeket, illetve kilépéskor mentheti vagy törölheti a tevékenységeket"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Fotó készítése"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Kép kiválasztása"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Fotó kiválasztása"</string> diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml index 2cd935205664..da8e714437e9 100644 --- a/packages/SettingsLib/res/values-hy/strings.xml +++ b/packages/SettingsLib/res/values-hy/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Զրոյացնել"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Հեռացնել"</string> <string name="guest_resetting" msgid="7822120170191509566">"Հյուրի աշխատաշրջանը վերակայվում է…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Վերակայե՞լ հյուրի աշխատաշրջանը"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Կսկսվի հյուրի նոր աշխատաշրջան, իսկ նախորդ աշխատաշրջանի բոլոր հավելվածներն ու տվյալները կջնջվեն"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Դուրս գա՞լ հյուրի ռեժիմից"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Հյուրի ընթացիկ աշխատաշրջանի բոլոր հավելվածներն ու տվյալները կջնջվեն"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Դուրս գալ"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Պահե՞լ հյուրի ռեժիմի պատմությունը"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Պահեք ընթացիկ աշխատաշրջանի պատմությունը կամ ջնջեք հավելվածներն ու տվյալները"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Ջնջել"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Պահել"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Դուրս գալ հյուրի ռեժիմից"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Վերակայել հյուրի աշխատաշրջանը"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Դուրս գալ հյուրի ռեժիմից"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Դուրս գալու դեպքում ամբողջ պատմությունը կջնջվի"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Դուրս գալիս կարող եք պահել կամ ջնջել ձեր պատմությունը"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Վերակայեք աշխատաշրջանի պատմությունը հիմա կամ պահեք/ջնջեք այն դուրս գալիս"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Լուսանկարել"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Ընտրել պատկեր"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Ընտրեք լուսանկար"</string> diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml index da3c3e634f20..51fca5a3af77 100644 --- a/packages/SettingsLib/res/values-in/strings.xml +++ b/packages/SettingsLib/res/values-in/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Reset"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Hapus"</string> <string name="guest_resetting" msgid="7822120170191509566">"Mereset tamu …"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Reset sesi tamu?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Tindakan ini akan memulai sesi tamu baru dan menghapus semua aplikasi serta data dari sesi saat ini"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Keluar dari mode tamu?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Tindakan ini akan menghapus aplikasi dan data dari sesi tamu saat ini"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Keluar"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Simpan aktivitas tamu?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Anda bisa menyimpan aktivitas sesi saat ini atau menghapus semua aplikasi & data"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Hapus"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Simpan"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Keluar dari mode tamu"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Reset sesi tamu"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Keluar dari mode tamu"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Semua aktivitas akan dihapus saat Anda keluar"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Anda dapat menyimpan atau menghapus aktivitas saat keluar"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Reset untuk menghapus aktivitas sesi sekarang, atau Anda dapat menyimpan atau menghapus aktivitas saat keluar"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Ambil foto"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Pilih gambar"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Pilih foto"</string> diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml index e0ca6e35c985..3a1ab7fef74a 100644 --- a/packages/SettingsLib/res/values-is/strings.xml +++ b/packages/SettingsLib/res/values-is/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Endurstilla"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Fjarlægja"</string> <string name="guest_resetting" msgid="7822120170191509566">"Endurstillir gest…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Endurstilla gestalotu?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Þetta opnar nýja gestalotu og eyðir öllum forritum og gögnum úr núverandi lotu"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Loka gestastillingu?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Þetta eyðir forritum og gögnum úr núverandi gestalotu"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Hætta"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Vista aðgerðir úr gestalotu?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Þú getur vistað aðgerðir úr núverandi lotu eða eytt öllum forritum og gögnum"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Eyða"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Vista"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Loka gestastillingu"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Endurstilla gestalotu"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Loka gestastillingu"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Öllum aðgerðum verður eytt þegar lotu er lokað"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Þú getur vistað eða eytt aðgerðum þegar þú lokar"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Endurstilltu til að eyða aðgerðum lotu núna, eða þú getur vistað eða eytt aðgerðum þegar þú lokar"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Taka mynd"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Velja mynd"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Velja mynd"</string> diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml index 66c7273ab5d3..99aa1fdf4d13 100644 --- a/packages/SettingsLib/res/values-it/strings.xml +++ b/packages/SettingsLib/res/values-it/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Reimposta"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Rimuovi"</string> <string name="guest_resetting" msgid="7822120170191509566">"Reimpostazione sessione Ospite in corso…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Vuoi reimpostare la sessione Ospite?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Verrà avviata una nuova sessione Ospite e verranno eliminati tutti i dati e le app della sessione corrente"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Vuoi uscire da modalità Ospite?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Verranno eliminati i dati e le app della sessione Ospite corrente"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Esci"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Vuoi salvare l\'attività Ospite?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Puoi salvare l\'attività della sessione corrente o eliminare tutti i dati e app"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Elimina"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Salva"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Esci dalla modalità Ospite"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Reimposta sessione Ospite"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Esci dalla modalità Ospite"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Quando esci verrà eliminata tutta l\'attività"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Quando esci puoi salvare o eliminare la tua attività"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Reimposta per eliminare subito l\'attività della sessione oppure puoi salvare o eliminare l\'attività quando esci"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Scatta una foto"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Scegli un\'immagine"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Seleziona la foto"</string> diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml index 2196c75ddde6..fc70209f7d94 100644 --- a/packages/SettingsLib/res/values-iw/strings.xml +++ b/packages/SettingsLib/res/values-iw/strings.xml @@ -594,10 +594,25 @@ <string name="guest_exit_guest" msgid="5908239569510734136">"הסרת אורח"</string> <string name="guest_reset_guest" msgid="6110013010356013758">"איפוס הגלישה כאורח"</string> <string name="guest_reset_guest_dialog_title" msgid="8047270010895437534">"לאפס את הגלישה כאורח?"</string> - <string name="guest_remove_guest_dialog_title" msgid="4548511006624088072">"להסיר את האורח/ת?"</string> + <string name="guest_remove_guest_dialog_title" msgid="4548511006624088072">"להסיר את האורח?"</string> <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"איפוס"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"הסרה"</string> <string name="guest_resetting" msgid="7822120170191509566">"מתבצע איפוס של הגלישה כאורח…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"לאפס את הגלישה כאורח?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"הפעולה הזו תתחיל גלישה חדשה כאורח ותמחק את כל האפליקציות והנתונים מהסשן הנוכחי"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"לצאת ממצב אורח?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"הפעולה הזו תמחק את האפליקציות והנתונים מהגלישה הנוכחית כאורח"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"יציאה"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"לשמור את פעילות האורח?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"אפשר לשמור את הפעילות מהסשן הנוכחי או למחוק את כל האפליקציות והנתונים"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"מחיקה"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"שמירה"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"יציאה ממצב אורח"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"איפוס הגלישה כאורח"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"יציאה ממצב אורח"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"כל הפעילות תימחק ביציאה"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"אפשר לשמור או למחוק את הפעילות שלך ביציאה"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"ניתן לאפס כדי למחוק את הפעילות מהסשן כעת, או לשמור או למחוק את הפעילות ביציאה"</string> <string name="user_image_take_photo" msgid="467512954561638530">"צילום תמונה"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"לבחירת תמונה"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"בחירת תמונה"</string> diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml index ae428df2a285..c42cca676620 100644 --- a/packages/SettingsLib/res/values-ja/strings.xml +++ b/packages/SettingsLib/res/values-ja/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"リセット"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"削除"</string> <string name="guest_resetting" msgid="7822120170191509566">"ゲストをリセットしています…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"ゲスト セッションをリセットしますか?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"新しいゲスト セッションが開始し、現在のセッションのすべてのアプリとデータが削除されます"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"ゲストモードを終了しますか?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"現在のゲスト セッションからすべてのアプリとデータが削除されます"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"終了"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"ゲストのアクティビティを保存しますか?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"現在のセッションのアクティビティの保存や、すべてのアプリとデータの削除を行えます"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"削除"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"保存"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"ゲストモードを終了"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"ゲスト セッションをリセット"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"ゲストを終了"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"終了時にすべてのアクティビティが削除されます"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"終了時にアクティビティを保存、削除できます"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"リセットして今すぐセッションのアクティビティを削除します(終了時にアクティビティを保存、削除することもできます)"</string> <string name="user_image_take_photo" msgid="467512954561638530">"写真を撮る"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"画像を選択"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"写真を選択"</string> diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml index c6a50ac9e565..525a0d235fd2 100644 --- a/packages/SettingsLib/res/values-ka/strings.xml +++ b/packages/SettingsLib/res/values-ka/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"გადაყენება"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"ამოშლა"</string> <string name="guest_resetting" msgid="7822120170191509566">"მიმდინარეობს სტუმრის გადაყენება…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"გსურთ სტუმრის სესიის გადაყენება?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"ამ ქმედებით დაიწყება სტუმრის ახალი სესია და წაიშლება ყველა აპი და მონაცემი მიმდინარე სესიიდან"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"გსურთ სტუმრის რეჟიმიდან გასვლა?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"ეს ქმედება წაშლის აპებსა და მონაცემებს სტუმრის რეჟიმის მიმდინარე სესიიდან"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"გასვლა"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"გსურთ სტუმრის აქტივობის შენახვა?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"შეგიძლიათ შეინახოთ აქტივობა მიმდინარე სესიიდან ან წაშალოთ ყველა აპი და მონაცემი"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"წაშლა"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"შენახვა"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"სტუმრის რეჟიმიდან გასვლა"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"სტუმრის სესიის გადაყენება"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"სტუმრის გასვლა"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"გასვლისას ყველა აქტივობა წაიშლება"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"გასვლისას შეგიძლიათ შეინახოთ ან წაშალოთ თქვენი აქტივობა"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"გადააყენეთ სესიის აქტივობის ახლავე წასაშლელად, ასევე, შეინახეთ ან წაშალეთ აქტივობა გასვლისას"</string> <string name="user_image_take_photo" msgid="467512954561638530">"ფოტოს გადაღება"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"აირჩიეთ სურათი"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"ფოტოს არჩევა"</string> diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml index f5559d270f0a..90c716414764 100644 --- a/packages/SettingsLib/res/values-kk/strings.xml +++ b/packages/SettingsLib/res/values-kk/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Бастапқы күйге қайтару"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Өшіру"</string> <string name="guest_resetting" msgid="7822120170191509566">"Қонақ сеансы бастапқы күйге қайтарылуда…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Қонақ сеансын бастапқы күйге қайтару керек пе?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Мұндайда жаңа қонақ сеансы басталады және ағымдағы сеанстағы барлық қолданба мен дерек жойылады."</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Қонақ режимінен шығу керек пе?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Ағымдағы қонақ сеансындағы барлық қолданба мен дерек жойылады."</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Шығу"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Қонақ әрекетін сақтау керек пе?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Ағымдағы сеанстағы әрекетті сақтай не барлық қолданба мен деректі жоя аласыз."</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Жою"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Сақтау"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Қонақ режимінен шығу"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Иә"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Қонақ режимінен шығу"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Шыққанда барлық әрекет жойылады."</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Шыққанда барлық әрекетті сақтай немесе жоя аласыз."</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Сеанс әрекетін қазір жою үшін оны бастапқы күйге қайтарыңыз. Әрекетті сақтау немесе жою шешімін шыққан кезде қабылдай аласыз."</string> <string name="user_image_take_photo" msgid="467512954561638530">"Фотосуретке түсіру"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Сурет таңдау"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Фотосурет таңдау"</string> diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml index a770f61f2acf..6d284be67135 100644 --- a/packages/SettingsLib/res/values-km/strings.xml +++ b/packages/SettingsLib/res/values-km/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"កំណត់ឡើងវិញ"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"ដកចេញ"</string> <string name="guest_resetting" msgid="7822120170191509566">"កំពុងកំណត់ភ្ញៀវឡើងវិញ…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"កំណត់វគ្គភ្ញៀវឡើងវិញឬ?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"ការធ្វើបែបនេះនឹងចាប់ផ្ដើមវគ្គភ្ញៀវថ្មី និងលុបកម្មវិធី និងទិន្នន័យទាំងអស់ចេញពីវគ្គបច្ចុប្បន្ន"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"ចាកចេញពីមុខងារភ្ញៀវឬ?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"ការធ្វើបែបនេះនឹងលុបកម្មវិធី និងទិន្នន័យចេញពីវគ្គភ្ញៀវបច្ចុប្បន្ន"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"ចាកចេញ"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"រក្សាទុកសកម្មភាពភ្ញៀវឬ?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"អ្នកអាចរក្សាទុកសកម្មភាពពីវគ្គបច្ចុប្បន្ន ឬលុបកម្មវិធីនិងទិន្នន័យទាំងអស់"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"លុប"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"រក្សាទុក"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"ចាកចេញពីមុខងារភ្ញៀវ"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"កំណត់វគ្គភ្ញៀវឡើងវិញ"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"ចាកចេញពីមុខងារភ្ញៀវ"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"សកម្មភាពទាំងអស់នឹងត្រូវលុបនៅពេលចាកចេញ"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"អ្នកអាចរក្សាទុក ឬលុបសកម្មភាពរបស់អ្នកនៅពេលចាកចេញ"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"កំណត់ឡើងវិញ ដើម្បីលុបសកម្មភាពក្នុងវគ្គឥឡូវនេះ ឬអ្នកអាចរក្សាទុកឬលុបសកម្មភាពនៅពេលចាកចេញ"</string> <string name="user_image_take_photo" msgid="467512954561638530">"ថតរូប"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"ជ្រើសរើសរូបភាព"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"ជ្រើសរើសរូបថត"</string> diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml index f4ee0a709e57..5e5221fee866 100644 --- a/packages/SettingsLib/res/values-kn/strings.xml +++ b/packages/SettingsLib/res/values-kn/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"ರೀಸೆಟ್ ಮಾಡಿ"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"ತೆಗೆದುಹಾಕಿ"</string> <string name="guest_resetting" msgid="7822120170191509566">"ಅತಿಥಿ ಬಳಕೆದಾರರ ಸೆಟ್ಟಿಂಗ್ ಅನ್ನು ರೀಸೆಟ್ ಮಾಡಲಾಗುತ್ತಿದೆ…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"ಅತಿಥಿ ಸೆಷನ್ ಅನ್ನು ರೀಸೆಟ್ ಮಾಡಬೇಕೇ?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"ಈ ಪ್ರಕ್ರಿಯೆಯು ಹೊಸ ಅತಿಥಿ ಸೆಶನ್ ಅನ್ನು ಪ್ರಾರಂಭಿಸುತ್ತದೆ ಮತ್ತು ಪ್ರಸ್ತುತ ಸೆಶನ್ನಿಂದ ಎಲ್ಲಾ ಆ್ಯಪ್ಗಳು ಹಾಗೂ ಡೇಟಾವನ್ನು ಅಳಿಸುತ್ತದೆ"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"ಅತಿಥಿ ಮೋಡ್ನಿಂದ ನಿರ್ಗಮಿಸಬೇಕೆ?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"ಈ ಪ್ರಕ್ರಿಯೆಯು ಪ್ರಸ್ತುತ ಅತಿಥಿ ಸೆಷನ್ನಿಂದ ಆ್ಯಪ್ಗಳು ಮತ್ತು ಡೇಟಾವನ್ನು ಅಳಿಸುತ್ತದೆ"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"ನಿರ್ಗಮಿಸಿ"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"ಅತಿಥಿ ಚಟುವಟಿಕೆಯನ್ನು ಉಳಿಸಬೇಕೆ?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"ನೀವು ಪ್ರಸ್ತುತ ಸೆಶನ್ನ ಚಟುವಟಿಕೆಯನ್ನು ಉಳಿಸಬಹುದು ಅಥವಾ ಎಲ್ಲಾ ಆ್ಯಪ್ಗಳು ಮತ್ತು ಡೇಟಾವನ್ನು ಅಳಿಸಬಹುದು"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"ಅಳಿಸಿ"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"ಉಳಿಸಿ"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"ಅತಿಥಿ ಮೋಡ್ನಿಂದ ನಿರ್ಗಮಿಸಿ"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"ಅತಿಥಿ ಸೆಷನ್ ಅನ್ನು ರೀಸೆಟ್ ಮಾಡಿ"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"ಅತಿಥಿ ಮೋಡ್ನಿಂದ ನಿರ್ಗಮಿಸಿ"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"ನಿರ್ಗಮಿಸುವಾಗ ಎಲ್ಲಾ ಚಟುವಟಿಕೆಯನ್ನು ಅಳಿಸಲಾಗುತ್ತದೆ"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"ನಿರ್ಗಮಿಸುವಾಗ ನಿಮ್ಮ ಚಟುವಟಿಕೆಯನ್ನು ನೀವು ಉಳಿಸಬಹುದು ಅಥವಾ ಅಳಿಸಬಹುದು"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"ಸೆಶನ್ ಚಟುವಟಿಕೆಯನ್ನು ಈಗ ಅಳಿಸಲು ರೀಸೆಟ್ ಮಾಡಿ ಅಥವಾ ನಿರ್ಗಮಿಸುವಾಗ ನೀವು ಚಟುವಟಿಕೆಯನ್ನು ಉಳಿಸಬಹುದು ಅಥವಾ ಅಳಿಸಬಹುದು"</string> <string name="user_image_take_photo" msgid="467512954561638530">"ಫೋಟೋ ತೆಗೆದುಕೊಳ್ಳಿ"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"ಚಿತ್ರವನ್ನು ಆರಿಸಿ"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"ಫೋಟೋ ಆಯ್ಕೆಮಾಡಿ"</string> diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml index 7a97242e9af5..f4889325dea3 100644 --- a/packages/SettingsLib/res/values-ko/strings.xml +++ b/packages/SettingsLib/res/values-ko/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"재설정"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"삭제"</string> <string name="guest_resetting" msgid="7822120170191509566">"게스트 재설정 중…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"게스트 세션을 재설정하시겠습니까?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"이렇게 하면 새로운 게스트 세션이 시작되고 기존 세션의 모든 앱과 데이터가 삭제됩니다."</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"게스트 모드를 종료하시겠습니까?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"기존 게스트 세션의 앱과 데이터가 삭제됩니다."</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"종료"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"게스트 활동을 저장하시겠습니까?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"기존 세션의 활동을 저장하거나 모든 앱과 데이터를 삭제할 수 있습니다."</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"삭제"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"저장"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"게스트 모드 종료"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"게스트 세션 재설정"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"게스트 종료"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"종료하면 모든 활동이 삭제됩니다."</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"종료 시 활동을 저장하거나 삭제할 수 있습니다."</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"지금 재설정하여 활동 세션을 삭제하거나 종료 시 활동을 저장 또는 삭제할 수 있습니다."</string> <string name="user_image_take_photo" msgid="467512954561638530">"사진 찍기"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"이미지 선택"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"사진 선택"</string> diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml index 8af2627c8e9c..aa94537121e1 100644 --- a/packages/SettingsLib/res/values-ky/strings.xml +++ b/packages/SettingsLib/res/values-ky/strings.xml @@ -95,7 +95,7 @@ <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Ажыратылууда…"</string> <string name="bluetooth_connecting" msgid="5871702668260192755">"Туташууда…"</string> <string name="bluetooth_connected" msgid="8065345572198502293">"Туташып турат<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> - <string name="bluetooth_pairing" msgid="4269046942588193600">"Жупташтырылууда…"</string> + <string name="bluetooth_pairing" msgid="4269046942588193600">"Туташууда…"</string> <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"Туташып турат (телефониясыз)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> <string name="bluetooth_connected_no_a2dp" msgid="8566874395813947092">"Туташып турат (медиасыз)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> <string name="bluetooth_connected_no_map" msgid="3381860077002724689">"Туташып турат (SMS/MMS жазышуусуз)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> @@ -150,7 +150,7 @@ <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"ЖУПТАШТЫРУУ"</string> <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Жок"</string> <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"Жупташканда байланыштарыңыз менен чалуу таржымалыңызды пайдалана аласыз."</string> - <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> менен жупташуу мүмкүн эмес."</string> + <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> түзмөгүнө туташуу мүмкүн болгон жок."</string> <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"PIN-код же сырсөз туура эмес болгондуктан, \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\" түзмөгүнө туташуу мүмкүн болгон жок."</string> <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> менен байланышуу мүмкүн эмес."</string> <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"Жупташтырууну <xliff:g id="DEVICE_NAME">%1$s</xliff:g> четке какты."</string> @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Баштапкы абалга келтирүү"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Өчүрүү"</string> <string name="guest_resetting" msgid="7822120170191509566">"Конок сеансы баштапкы абалга келтирилүүдө…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Конок сеансы баштапкы абалга келтирилсинби?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Бул аракет жаңы конок сеансын баштап, учурдагы сеанстагы бардык колдонмолорду жана дайындарды жок кылат"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Конок режиминен чыгасызбы?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Бул учурдагы конок сеансындагы колдонмолорду жана дайындарды жок кылат"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Чыгуу"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Коноктун аракеттери сакталсынбы?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Учурдагы сеанстагы аракеттерди сактап же бардык колдонмолорду жана дайындарды жок кылсаңыз болот"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Өчүрүү"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Сактоо"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Конок режиминен чыгуу"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Конок сеансын кайра коюу"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Конок режиминен чыгуу"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Чыксаңыз, бардык аракеттер өчүрүлөт"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Чыгуудан мурун аракеттериңизди сактап же жок кылсаңыз болот"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Сеанстагы аракеттерди азыр жок кылуу үчүн баштапкы абалга келтириңиз, же болбосо чыгуу учурунда аракеттерди сактап же жок кылсаңыз болот"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Сүрөткө тартуу"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Сүрөт тандаңыз"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Сүрөт тандаңыз"</string> diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml index 5c0f1921b665..3d5925ab2de0 100644 --- a/packages/SettingsLib/res/values-lo/strings.xml +++ b/packages/SettingsLib/res/values-lo/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"ຣີເຊັດ"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"ລຶບອອກ"</string> <string name="guest_resetting" msgid="7822120170191509566">"ກຳລັງຣີເຊັດແຂກ…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"ຣີເຊັດໄລຍະເວລາຂອງແຂກບໍ?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"ນີ້ຈະເລີ່ມໄລຍະເວລາຂອງແຂກໃໝ່ ແລະ ລຶບແອັບ ແລະ ຂໍ້ມູນທັງໝົດອອກຈາກເຊດຊັນປັດຈຸບັນ"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"ອອກຈາກໂໝດແຂກບໍ?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"ນີ້ຈະລຶບແອັບ ແລະ ຂໍ້ມູນອອກຈາກໄລຍະເວລາຂອງແຂກປັດຈຸບັນ"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"ອອກ"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"ບັນທຶກການເຄື່ອນໄຫວແຂກບໍ?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"ທ່ານສາມາດບັນທຶກການເຄື່ອນໄຫວຈາກເຊດຊັນປັດຈຸບັນ ຫຼື ລຶບແອັບ ແລະ ຂໍ້ມູນທັງໝົດໄດ້"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"ລຶບ"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"ບັນທຶກ"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"ອອກຈາກໂໝດແຂກ"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"ຣີເຊັດໄລຍະເວລາຂອງແຂກ"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"ອອກຈາກແຂກ"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"ການເຄື່ອນໄຫວທັງໝົດຈະຖືກລຶບໃນຕອນອອກ"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"ທ່ານສາມາດບັນທຶກ ຫຼື ລຶບການເຄື່ອນໄຫວຂອງທ່ານໃນຕອນອອກໄດ້"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"ຣີເຊັດເພື່ອລຶບການເຄື່ອນໄຫວເຊດຊັນຕອນນີ້ ຫຼື ທ່ານສາມາດບັນທຶກ ຫຼື ລຶບການເຄື່ອນໄຫວໃນຕອນອອກໄດ້"</string> <string name="user_image_take_photo" msgid="467512954561638530">"ຖ່າຍຮູບ"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"ເລືອກຮູບ"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"ເລືອກຮູບ"</string> diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml index 250d24af0d38..a161750e2098 100644 --- a/packages/SettingsLib/res/values-lt/strings.xml +++ b/packages/SettingsLib/res/values-lt/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Nustatyti iš naujo"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Pašalinti"</string> <string name="guest_resetting" msgid="7822120170191509566">"Svečias nustatomas iš naujo…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Nustatyti svečio sesiją iš naujo?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Bus pradėta nauja svečio sesija ir iš esamos sesijos bus ištrintos visos programos ir duomenys"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Išeiti iš svečio režimo?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Bus ištrintos esamos svečio sesijos programos ir duomenys"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Išeiti"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Išsaugoti svečio veiklą?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Galite išsaugoti esamos sesijos veiklą arba ištrinti visas programas ir duomenis"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Ištrinti"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Išsaugoti"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Išeiti iš svečio režimo"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Nustatyti svečio sesiją iš naujo"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Išeiti iš svečio režimo"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Išėjus iš režimo visa veikla bus ištrinta"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Išeidami galite išsaugoti arba ištrinti savo veiklą"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Nustatykite iš naujo, jei norite ištrinti sesijos veiklą dabar, arba galite išeidami išsaugoti ar ištrinti veiklą"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Fotografuoti"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Pasirinkti vaizdą"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Pasirinkti nuotrauką"</string> diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml index f72ba8e996fe..929b857950ff 100644 --- a/packages/SettingsLib/res/values-lv/strings.xml +++ b/packages/SettingsLib/res/values-lv/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Atiestatīt"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Noņemt"</string> <string name="guest_resetting" msgid="7822120170191509566">"Notiek viesa sesijas atiestatīšana…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Vai atiestatīt viesa sesiju?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Tādējādi tiks sākta jauna viesa sesijas un visas pašreizējās sesijas lietotnes un dati tiks dzēsti"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Vai iziet no viesa režīma?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Tādējādi tiks dzēstas pašreizējās viesa sesijas lietotnes un dati."</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Iziet"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Vai saglabāt viesa darbības?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Varat saglabāt pašreizējās sesijas darbības vai dzēst visas lietotnes un datus"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Dzēst"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Saglabāt"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Iziet no viesa režīma"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Atiestatīt viesa sesiju"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Iziet no viesa režīma"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Izejot tiks dzēstas visas darbības"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Izejot varat saglabāt vai dzēst savas darbības"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Atiestatiet, lai tagad dzēstu sesijas darbības. Izejot varēsiet saglabāt vai dzēst darbības."</string> <string name="user_image_take_photo" msgid="467512954561638530">"Uzņemt fotoattēlu"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Izvēlēties attēlu"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Atlasīt fotoattēlu"</string> diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml index 376452c78d4a..9a286913372c 100644 --- a/packages/SettingsLib/res/values-mk/strings.xml +++ b/packages/SettingsLib/res/values-mk/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Ресетирај"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Отстрани"</string> <string name="guest_resetting" msgid="7822120170191509566">"Се ресетира гостинот…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Да се ресетира гостинската сесија?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Ова ќе започне нова гостинска сесија и ќе ги избрише сите апликации и податоци од тековната сесија"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Да се излезе од режим на гостин?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Ова ќе ги избрише сите апликации и податоци од тековната гостинска сесија"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Излези"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Да се зачува активност на гостин?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Може да зачувате активност од тековната сесија или да ги избришете сите апликации и податоци"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Избриши"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Зачувај"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Излези од режим на гостин"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Ресетирај ја гостинската сесија"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Излези од режим на гостин"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Целата активност ќе се избрише при излегувањето"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Можете да ја зачувате или избришете вашата активност при излегувањето"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Ресетирајте за да ја избришете активноста на сесијата сега или може да ја зачувате или избришете активноста при излегувањето"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Фотографирајте"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Одберете слика"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Изберете фотографија"</string> diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml index e69d25f65c70..93b907be9548 100644 --- a/packages/SettingsLib/res/values-ml/strings.xml +++ b/packages/SettingsLib/res/values-ml/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"റീസെറ്റ് ചെയ്യുക"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"നീക്കം ചെയ്യുക"</string> <string name="guest_resetting" msgid="7822120170191509566">"അതിഥിയെ റീസെറ്റ് ചെയ്യുന്നു…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"അതിഥി സെഷൻ റീസെറ്റ് ചെയ്യണോ?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"ഇത് പുതിയൊരു അതിഥി സെഷൻ ആരംഭിക്കുകയും നിലവിലെ സെഷനിൽ നിന്ന് എല്ലാ ആപ്പുകളും ഡാറ്റയും ഇല്ലാതാക്കുകയും ചെയ്യും"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"അതിഥി മോഡിൽ നിന്ന് പുറത്തുകടക്കണോ?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"നിലവിലെ അതിഥി സെഷനിൽ നിന്ന് ആപ്പുകളും ഡാറ്റയും ഇത് ഇല്ലാതാക്കും"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"പുറത്തുകടക്കുക"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"അതിഥി ആക്റ്റിവിറ്റി സംരക്ഷിക്കണോ?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"നിലവിലെ സെഷനിൽ നിന്നുള്ള ആക്റ്റിവിറ്റി സംരക്ഷിക്കാം അല്ലെങ്കിൽ എല്ലാ ആപ്പുകളും ഡാറ്റയും ഇല്ലാതാക്കാം"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"ഇല്ലാതാക്കുക"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"സംരക്ഷിക്കുക"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"അതിഥി മോഡിൽ നിന്ന് പുറത്തുകടക്കുക"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"അതിഥി സെഷൻ റീസെറ്റ് ചെയ്യുക"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"അതിഥി മോഡിൽ നിന്ന് പുറത്തുകടക്കുക"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"പുറത്തുകടക്കുമ്പോൾ എല്ലാ ആക്റ്റിവിറ്റിയും ഇല്ലാതാക്കും"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"പുറത്തുകടക്കുമ്പോൾ ആക്റ്റിവിറ്റി സംരക്ഷിക്കുകയോ ഇല്ലാതാക്കുകയോ ചെയ്യാം"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"സെഷൻ ആക്റ്റിവിറ്റി ഇപ്പോൾ ഇല്ലാതാക്കാൻ റീസെറ്റ് ചെയ്യുക അല്ലെങ്കിൽ പുറത്തുകടക്കുമ്പോൾ ആക്റ്റിവിറ്റി സംരക്ഷിക്കുകയോ ഇല്ലാതാക്കുകയോ ചെയ്യാം"</string> <string name="user_image_take_photo" msgid="467512954561638530">"ഒരു ഫോട്ടോ എടുക്കുക"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"ഒരു ചിത്രം തിരഞ്ഞെടുക്കുക"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"ഫോട്ടോ തിരഞ്ഞെടുക്കുക"</string> diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml index cd41b81381d1..5eef7d386cc1 100644 --- a/packages/SettingsLib/res/values-mn/strings.xml +++ b/packages/SettingsLib/res/values-mn/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Шинэчлэх"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Хасах"</string> <string name="guest_resetting" msgid="7822120170191509566">"Зочныг шинэчилж байна…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Зочны харилцан үйлдлийг шинэчлэх үү?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Энэ нь шинэ зочны харилцан үйлдэл эхлүүлж, одоогийн харилцан үйлдлээс бүх апп болон өгөгдлийг устгана"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Зочны горимоос гарах уу?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Энэ нь одоогийн зочны харилцан үйлдлээс аппууд болон өгөгдлийг устгана"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Гарах"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Зочны үйл ажиллагааг хадгалах уу?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Та одоогийн харилцан үйлдлээс үйл ажиллагаа хадгалах эсвэл бүх апп, өгөгдлийг устгаж болно"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Устгах"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Хадгалах"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Зочны горимоос гарах"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Зочны харилцан үйлдлийг шинэчлэх"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Зочны горимоос гарах"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Бүх үйл ажиллагааг гарах үед устгана"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Та гарахдаа үйл ажиллагаагаа хадгалах эсвэл устгах боломжтой"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Харилцан үйлдлийн үйл ажиллагааг одоо устгахын тулд шинэчлэх эсвэл та гарахдаа үйл ажиллагааг хадгалах, устгах боломжтой"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Зураг авах"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Зураг сонгох"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Зураг сонгох"</string> diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml index 4006665cb12e..1611961f18c9 100644 --- a/packages/SettingsLib/res/values-mr/strings.xml +++ b/packages/SettingsLib/res/values-mr/strings.xml @@ -95,7 +95,7 @@ <string name="bluetooth_disconnecting" msgid="7638892134401574338">"डिस्कनेक्ट करत आहे..."</string> <string name="bluetooth_connecting" msgid="5871702668260192755">"कनेक्ट करत आहे..."</string> <string name="bluetooth_connected" msgid="8065345572198502293">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>कनेक्ट केले"</string> - <string name="bluetooth_pairing" msgid="4269046942588193600">"जोडत आहे…"</string> + <string name="bluetooth_pairing" msgid="4269046942588193600">"पेअर करत आहे…"</string> <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"कनेक्ट केले (फोन नाही)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> <string name="bluetooth_connected_no_a2dp" msgid="8566874395813947092">"कनेक्ट केले (मीडिया नाही)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> <string name="bluetooth_connected_no_map" msgid="3381860077002724689">"कनेक्ट केले (मेसेज अॅक्सेस नाही)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> @@ -151,7 +151,7 @@ <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"रद्द करा"</string> <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"कनेक्ट केल्यावर पेअरिंग तुमचे संपर्क आणि कॉल इतिहास यामध्ये अॅक्सेस देते."</string> <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> शी जोडू शकलो नाही."</string> - <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"अयोग्य पिन किंवा पासकीमुळे <xliff:g id="DEVICE_NAME">%1$s</xliff:g> सह जोडू शकलो नाही."</string> + <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"अयोग्य पिन किंवा पासकीमुळे <xliff:g id="DEVICE_NAME">%1$s</xliff:g> सह पेअर करू शकलो नाही."</string> <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> शी संवाद प्रस्थापित करू शकत नाही."</string> <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> द्वारे पेअरिंग नाकारले."</string> <string name="bluetooth_talkback_computer" msgid="3736623135703893773">"कॉंप्युटर"</string> @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"रीसेट करा"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"काढून टाका"</string> <string name="guest_resetting" msgid="7822120170191509566">"अतिथीला रीसेट करत आहे…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"अतिथी सत्र रीसेट करायचे का?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"हे नवीन अतिथी सत्र सुरू करेल आणि सध्याच्या सत्रातील सर्व अॅप्स व डेटा हटवेल"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"अतिथी मोडमधून बाहेर पडायचे का?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"हे सध्याच्या अतिथी सत्रातील अॅप्स आणि डेटा हटवेल"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"बाहेर पडा"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"अतिथी अॅक्टिव्हिटी सेव्ह करायची का?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"सध्याच्या सत्रातील अॅक्टिव्हिटी सेव्ह करू किंवा सर्व अॅप्स व डेटा हटवू शकता"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"हटवा"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"सेव्ह करा"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"अतिथी मोडमधून बाहेर पडा"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"अतिथी सत्र रीसेट करा"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"अतिथी मोडमधून बाहेर पडा"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"बाहेर पडल्यावर सर्व अॅक्टिव्हिटी हटवली जाईल"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"बाहेर पडल्यावर तुमची अॅक्टिव्हिटी सेव्ह करू किंवा हटवू शकता"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"सत्र अॅक्टिव्हिटी आता हटवण्यासाठी रीसेट करा किंवा तुम्ही बाहेर पडल्यावर अॅक्टिव्हिटी सेव्ह करू अथवा हटवू शकता"</string> <string name="user_image_take_photo" msgid="467512954561638530">"फोटो काढा"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"इमेज निवडा"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"फोटो निवडा"</string> diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml index 8a2fc2b0f450..79bb7a712e2b 100644 --- a/packages/SettingsLib/res/values-ms/strings.xml +++ b/packages/SettingsLib/res/values-ms/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Tetapkan semula"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Alih keluar"</string> <string name="guest_resetting" msgid="7822120170191509566">"Menetapkan semula tetamu…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Tetapkan semula sesi tetamu?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Tindakan ini akan memulakan sesi tetamu baharu dan memadamkan semua apl dan data daripada sesi semasa"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Keluar daripada mod tetamu?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Tindakan ini akan memadamkan apl dan data daripada sesi tetamu semasa"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Keluar"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Simpan aktiviti tetamu?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Anda boleh menyimpan aktiviti daripada sesi semasa atau memadamkan semua apl dan data"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Padam"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Simpan"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Keluar daripada mod tetamu"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Tetapkan semula sesi tetamu"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Keluar mod tetamu"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Semua aktiviti akan dipadamkan semasa keluar"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Aktiviti anda boleh disimpan atau dipadam semasa keluar"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Tetapkan semula sesi untuk memadamkan aktiviti sesi sekarang atau anda boleh menyimpan atau memadamkan aktiviti semasa keluar"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Ambil foto"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Pilih imej"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Pilih foto"</string> diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml index 98bac84ac706..a4325315291a 100644 --- a/packages/SettingsLib/res/values-my/strings.xml +++ b/packages/SettingsLib/res/values-my/strings.xml @@ -95,7 +95,7 @@ <string name="bluetooth_disconnecting" msgid="7638892134401574338">"အဆက်အသွယ်ဖြတ်တောက်သည်"</string> <string name="bluetooth_connecting" msgid="5871702668260192755">"ချိတ်ဆက်နေသည်"</string> <string name="bluetooth_connected" msgid="8065345572198502293">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> ချိတ်ဆက်ပြီးပြီ"</string> - <string name="bluetooth_pairing" msgid="4269046942588193600">"တွဲချိတ်ပါ"</string> + <string name="bluetooth_pairing" msgid="4269046942588193600">"တွဲချိတ်နေသည်…"</string> <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> ချိတ်ဆက်ပြီးပြီ (ဖုန်းမရှိပါ)"</string> <string name="bluetooth_connected_no_a2dp" msgid="8566874395813947092">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> ချိတ်ဆက်ပြီးပြီ (မီဒီယာ မရှိပါ)"</string> <string name="bluetooth_connected_no_map" msgid="3381860077002724689">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> ချိတ်ဆက်ပြီးပြီ (မက်ဆေ့ဂျ် သုံး၍မရပါ)"</string> @@ -599,6 +599,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"ပြင်ဆင်သတ်မှတ်ရန်"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"ဖယ်ရှားရန်"</string> <string name="guest_resetting" msgid="7822120170191509566">"ဧည့်သည်ကို ပြင်ဆင်သတ်မှတ်နေသည်…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"ဧည့်သည် စက်ရှင် ပြင်ဆင်သတ်မှတ်မလား။"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"၎င်းသည် ဧည့်သည် စက်ရှင်အသစ်ကို စတင်မည်ဖြစ်ပြီး လက်ရှိစက်ရှင်မှ အက်ပ်နှင့် ဒေတာအားလုံးကို ဖျက်ပါမည်"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"ဧည့်သည်မုဒ်မှ ထွက်မလား။"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"၎င်းသည် လက်ရှိဧည့်သည် စက်ရှင်မှ အက်ပ်နှင့် ဒေတာအားလုံးကို ဖျက်လိုက်ပါမည်"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"ထွက်ရန်"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"ဧည့်သည်လုပ်ဆောင်ချက် သိမ်းမလား။"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"လက်ရှိစက်ရှင်မှ လုပ်ဆောင်ချက် သိမ်းနိုင်သည် (သို့) အက်ပ်နှင့် ဒေတာအားလုံး ဖျက်နိုင်သည်"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"ဖျက်ရန်"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"သိမ်းရန်"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"ဧည့်သည်မုဒ်မှ ထွက်ရန်"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"ဧည့်သည် စက်ရှင် ပြင်ဆင်သတ်မှတ်ရန်"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"ဧည့်သည့်မှ ထွက်ရန်"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"ထွက်သည့်အခါ လုပ်ဆောင်ချက်အားလုံးကို ဖျက်လိုက်မည်"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"ထွက်သည့်အခါ လုပ်ဆောင်ချက်ကို သိမ်းနိုင် (သို့) ဖျက်နိုင်သည်"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"စက်ရှင်လုပ်ဆောင်ချက်ကို ယခုဖျက်ရန် ပြင်ဆင်သတ်မှတ်နိုင်သည် (သို့) ထွက်သည့်အခါ လုပ်ဆောင်ချက်ကို သိမ်းနိုင် (သို့) ဖျက်နိုင်သည်"</string> <string name="user_image_take_photo" msgid="467512954561638530">"ဓာတ်ပုံရိုက်ရန်"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"ပုံရွေးရန်"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"ဓာတ်ပုံရွေးရန်"</string> diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml index 13bdd7e90dbc..013737ca6234 100644 --- a/packages/SettingsLib/res/values-nb/strings.xml +++ b/packages/SettingsLib/res/values-nb/strings.xml @@ -95,7 +95,7 @@ <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Kobler fra…"</string> <string name="bluetooth_connecting" msgid="5871702668260192755">"Kobler til…"</string> <string name="bluetooth_connected" msgid="8065345572198502293">"Koblet til <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> - <string name="bluetooth_pairing" msgid="4269046942588193600">"Sammenkobles …"</string> + <string name="bluetooth_pairing" msgid="4269046942588193600">"Kobler til …"</string> <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"Koblet til (ingen telefon) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> <string name="bluetooth_connected_no_a2dp" msgid="8566874395813947092">"Koblet til (ingen medier) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> <string name="bluetooth_connected_no_map" msgid="3381860077002724689">"Koblet til (ingen meldingstilgang) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> @@ -570,7 +570,7 @@ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Begrenset profil"</string> <string name="user_add_user_title" msgid="5457079143694924885">"Vil du legge til en ny bruker?"</string> <string name="user_add_user_message_long" msgid="1527434966294733380">"Du kan dele denne enheten med andre folk ved å opprette flere brukere. Hver bruker har sin egen plass de kan tilpasse med apper, bakgrunner og annet. Brukere kan også justere enhetsinnstillinger, for eksempel Wi-Fi, som påvirker alle.\n\nNår du legger til en ny bruker, må vedkommende angi innstillinger for plassen sin.\n\nAlle brukere kan oppdatere apper for alle andre brukere. Innstillinger og tjenester for tilgjengelighet overføres kanskje ikke til den nye brukeren."</string> - <string name="user_add_user_message_short" msgid="3295959985795716166">"Når du legger til en ny bruker, må vedkommende konfigurere sitt eget område.\n\nAlle brukere kan oppdatere apper for alle andre brukere."</string> + <string name="user_add_user_message_short" msgid="3295959985795716166">"Når du legger til en ny bruker, må hen konfigurere sitt eget område.\n\nAlle brukere kan oppdatere apper for alle andre brukere."</string> <string name="user_setup_dialog_title" msgid="8037342066381939995">"Konfigurere brukeren nå?"</string> <string name="user_setup_dialog_message" msgid="269931619868102841">"Sørg for at brukeren er tilgjengelig for å konfigurere området sitt på enheten"</string> <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Vil du konfigurere profilen nå?"</string> @@ -590,7 +590,7 @@ <string name="add_guest_failed" msgid="8074548434469843443">"Kunne ikke opprette en ny gjest"</string> <string name="user_nickname" msgid="262624187455825083">"Kallenavn"</string> <string name="user_add_user" msgid="7876449291500212468">"Legg til bruker"</string> - <string name="guest_new_guest" msgid="3482026122932643557">"Legg til en gjest"</string> + <string name="guest_new_guest" msgid="3482026122932643557">"Legg til gjest"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Fjern gjesten"</string> <string name="guest_reset_guest" msgid="6110013010356013758">"Tilbakestill gjest"</string> <string name="guest_reset_guest_dialog_title" msgid="8047270010895437534">"Vil du tilbakestille gjesten?"</string> @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Tilbakestill"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Fjern"</string> <string name="guest_resetting" msgid="7822120170191509566">"Tilbakestiller gjesten …"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Vil du tilbakestille gjesteøkten?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Dette starter en ny gjesteøkt og sletter alle apper og data fra den gjeldende økten"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Vil du avslutte gjestemodus?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Dette sletter apper og data fra den gjeldende gjesteøkten"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Avslutt"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Vil du lagre gjesteaktivitet?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Du kan lagre aktivitet fra den gjeldende økten eller slette alle apper og data"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Slett"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Lagre"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Avslutt gjestemodus"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Tilbakestill gjesteøkten"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Avslutt gjesteøkten"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"All aktivitet slettes når du avslutter"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Du kan lagre eller slette aktiviteten når du avslutter"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Tilbakestill for å slette øktaktivitet nå, eller du kan lagre eller slette aktivitet når du avslutter"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Ta et bilde"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Velg et bilde"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Velg et bilde"</string> diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml index 30401ace32ed..414f08ddd279 100644 --- a/packages/SettingsLib/res/values-ne/strings.xml +++ b/packages/SettingsLib/res/values-ne/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"रिसेट गर्नुहोस्"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"हटाउनुहोस्"</string> <string name="guest_resetting" msgid="7822120170191509566">"अतिथिका रूपमा ब्राउज गर्ने सेसन रिसेट गरिँदै छ…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"अतिथि सत्र रिसेट गर्ने हो?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"यसो गर्नाले नयाँ अतिथि सत्र सुरु हुने छ र हालको अतिथि सत्रका सबै एप तथा डेटा मेटिने छ"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"अतिथि मोडबाट बाहिरिने हो?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"यसो गर्नाले हालको अतिथि सत्रका एप तथा डेटा मेटिने छ"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"बाहिरिनुहोस्"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"अतिथि सत्रमा गरिएका क्रियाकलाप सेभ गर्ने हो?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"तपाईं हालको सत्रमा गरिएका क्रियाकलाप सेभ गर्न वा सबै एप तथा डेटा मेटाउन सक्नुहुन्छ"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"मेटाउनुहोस्"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"सेभ गर्नुहोस्"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"अतिथि मोडबाट बाहिरिनुहोस्"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"अतिथि सत्र रिसेट गर्नुहोस्"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"अतिथि मोडबाट बाहिरिनुहोस्"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"अतिथि मोडबाट बाहिरिँदा सबै क्रियाकलाप मेटाइने छ"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"तपाईं अतिथि मोडबाट बाहिरिँदा आफ्ना क्रियाकलाप सेभ गर्ने वा मेटाउने विकल्प रोज्न सक्नुहुन्छ"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"यो सत्रमा गरिएका क्रियाकलाप अहिले नै मेटाउन रिसेट गर्नुहोस्, अथवा तपाईं अतिथि मोडबाट बाहिरिँदा आफ्ना क्रियाकलाप सेभ गर्ने वा मेटाउने विकल्प रोज्न सक्नुहुन्छ"</string> <string name="user_image_take_photo" msgid="467512954561638530">"फोटो खिच्नुहोस्"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"कुनै फोटो छनौट गर्नुहोस्"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"फोटो चयन गर्नुहोस्"</string> diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml index c5065cb364bb..20fe50282087 100644 --- a/packages/SettingsLib/res/values-nl/strings.xml +++ b/packages/SettingsLib/res/values-nl/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Resetten"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Verwijderen"</string> <string name="guest_resetting" msgid="7822120170191509566">"Gast resetten…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Gastsessie resetten?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Hierdoor wordt een nieuwe gastsessie gestart en worden alle apps en gegevens van de huidige sessie verwijderd"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Gastmodus sluiten?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Hierdoor worden apps en gegevens van de huidige gastsessie verwijderd"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Sluiten"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Gastactiviteit opslaan?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Sla activiteit van de huidige sessie op of verwijder alle apps en gegevens"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Verwijderen"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Opslaan"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Gastmodus sluiten"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Gastsessie resetten"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Gastmodus verlaten"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Alle activiteit wordt na het afsluiten verwijderd"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Je kunt je activiteit bij afsluiten opslaan of verwijderen"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Voer een reset uit om de sessie-activiteit nu te verwijderen of verwijder of sla je activiteit op bij afsluiten"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Foto maken"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Afbeelding kiezen"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Foto selecteren"</string> diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml index 337dd79735f6..b10579bfce73 100644 --- a/packages/SettingsLib/res/values-or/strings.xml +++ b/packages/SettingsLib/res/values-or/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"ରିସେଟ୍ କରନ୍ତୁ"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"କାଢ଼ି ଦିଅନ୍ତୁ"</string> <string name="guest_resetting" msgid="7822120170191509566">"ଅତିଥି ସେସନକୁ ରିସେଟ୍ କରାଯାଉଛି…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"ଅତିଥି ସେସନକୁ ରିସେଟ କରିବେ?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"ଏହା ଏକ ନୂଆ ଅତିଥି ସେସନ ଆରମ୍ଭ କରିବ ଏବଂ ବର୍ତ୍ତମାନର ସେସନରୁ ସମସ୍ତ ଆପ୍ସ ଏବଂ ଡାଟାକୁ ଡିଲିଟ କରିବ"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"ଅତିଥି ମୋଡରୁ ବାହାରି ଯିବେ?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"ଏହା ବର୍ତ୍ତମାନର ଅତିଥି ସେସନରୁ ଆପ୍ସ ଏବଂ ଡାଟାକୁ ଡିଲିଟ କରିବ"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"ବାହାରି ଯାଆନ୍ତୁ"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"ଅତିଥି କାର୍ଯ୍ୟକଳାପ ସେଭ କରିବେ?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"ଆପଣ ଏବେର ସେସନରୁ କାର୍ଯ୍ୟକଳାପକୁ ସେଭ କରିପାରିବେ ବା ସବୁ ଆପ୍ସ ଓ ଡାଟାକୁ ଡିଲିଟ କରିପାରିବେ"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"ଡିଲିଟ କରନ୍ତୁ"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"ସେଭ କରନ୍ତୁ"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"ଅତିଥି ମୋଡରୁ ବାହାରି ଯାଆନ୍ତୁ"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"ଅତିଥି ସେସନକୁ ରିସେଟ କରନ୍ତୁ"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"ଅତିଥି ମୋଡରୁ ବାହାରି ଯାଆନ୍ତୁ"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"ବାହାରିବା ସମୟରେ ସମସ୍ତ କାର୍ଯ୍ୟକଳାପକୁ ଡିଲିଟ କରାଯିବ"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"ବାହାରିବା ସମୟରେ ଆପଣଙ୍କର କାର୍ଯ୍ୟକଳାପକୁ ସେଭ ବା ଡିଲିଟ କରିପାରିବେ"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"ବର୍ତ୍ତମାନ ସେସନ କାର୍ଯ୍ୟକଳାପକୁ ଡିଲିଟ କରିବାକୁ ରିସେଟ କରନ୍ତୁ କିମ୍ବା ବାହାରିବା ସମୟରେ ଆପଣ କାର୍ଯ୍ୟକଳାପକୁ ସେଭ କିମ୍ବା ଡିଲିଟ କରିପାରିବେ"</string> <string name="user_image_take_photo" msgid="467512954561638530">"ଗୋଟିଏ ଫଟୋ ଉଠାନ୍ତୁ"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"ଏକ ଛବି ବାଛନ୍ତୁ"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"ଫଟୋ ବାଛନ୍ତୁ"</string> diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml index 0da516c80698..99eae56b0196 100644 --- a/packages/SettingsLib/res/values-pa/strings.xml +++ b/packages/SettingsLib/res/values-pa/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"ਰੀਸੈੱਟ ਕਰੋ"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"ਹਟਾਓ"</string> <string name="guest_resetting" msgid="7822120170191509566">"ਮਹਿਮਾਨ ਨੂੰ ਰੀਸੈੱਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"ਕੀ ਮਹਿਮਾਨ ਸੈਸ਼ਨ ਨੂੰ ਰੀਸੈੱਟ ਕਰਨਾ ਹੈ?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"ਇਸ ਨਾਲ ਨਵਾਂ ਮਹਿਮਾਨ ਸੈਸ਼ਨ ਸ਼ੁਰੂ ਹੋ ਜਾਵੇਗਾ ਅਤੇ ਮੌਜੂਦਾ ਸੈਸ਼ਨ ਦੀਆਂ ਸਾਰੀਆਂ ਐਪਾਂ ਅਤੇ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"ਕੀ ਮਹਿਮਾਨ ਮੋਡ ਤੋਂ ਬਾਹਰ ਜਾਣਾ ਹੈ?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"ਇਸ ਨਾਲ ਮੌਜੂਦਾ ਮਹਿਮਾਨ ਸੈਸ਼ਨ ਦੀਆਂ ਸਾਰੀਆਂ ਐਪਾਂ ਅਤੇ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"ਬਾਹਰ ਜਾਓ"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"ਕੀ ਮਹਿਮਾਨ ਸਰਗਰਮੀ ਰੱਖਿਅਤ ਕਰਨੀ ਹੈ?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"ਤੁਸੀਂ ਮੌਜੂਦਾ ਸੈਸ਼ਨ ਦੀ ਸਰਗਰਮੀ ਨੂੰ ਰੱਖਿਅਤ ਕਰ ਸਕਦੇ ਹੋ ਜਾਂ ਸਾਰੀਆਂ ਐਪਾਂ ਅਤੇ ਡਾਟਾ ਮਿਟਾ ਸਕਦੇ ਹੋ"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"ਮਿਟਾਓ"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"ਰੱਖਿਅਤ ਕਰੋ"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"ਮਹਿਮਾਨ ਮੋਡ ਤੋਂ ਬਾਹਰ ਜਾਓ"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"ਮਹਿਮਾਨ ਸੈਸ਼ਨ ਨੂੰ ਰੀਸੈੱਟ ਕਰੋ"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"ਮਹਿਮਾਨ ਮੋਡ ਤੋਂ ਬਾਹਰ ਜਾਓ"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"ਬਾਹਰ ਜਾਣ \'ਤੇ ਸਾਰੀ ਸਰਗਰਮੀ ਮਿਟਾਈ ਜਾਵੇਗੀ"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"ਤੁਸੀਂ ਬਾਹਰ ਜਾਣ \'ਤੇ ਆਪਣੀ ਸਭ ਸਰਗਰਮੀ ਰੱਖਿਅਤ ਕਰ ਜਾਂ ਮਿਟਾ ਸਕਦੇ ਹੋ"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"ਸੈਸ਼ਨ ਦੀ ਸਰਗਰਮੀ ਮਿਟਾਉਣ ਹੁਣੇ ਲਈ ਰੀਸੈੱਟ ਕਰੋ ਜਾਂ ਤੁਸੀਂ ਬਾਹਰ ਜਾਣ \'ਤੇ ਸਰਗਰਮੀ ਨੂੰ ਰੱਖਿਅਤ ਕਰ ਜਾਂ ਮਿਟਾ ਸਕਦੇ ਹੋ"</string> <string name="user_image_take_photo" msgid="467512954561638530">"ਇੱਕ ਫ਼ੋਟੋ ਖਿੱਚੋ"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"ਕੋਈ ਚਿੱਤਰ ਚੁਣੋ"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"ਫ਼ੋਟੋ ਚੁਣੋ"</string> diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml index aa5359af1fc2..945a0ce044a9 100644 --- a/packages/SettingsLib/res/values-pl/strings.xml +++ b/packages/SettingsLib/res/values-pl/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Resetuj"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Usuń"</string> <string name="guest_resetting" msgid="7822120170191509566">"Resetuję sesję gościa…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Zresetować sesję gościa?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Zostanie uruchomiona nowa sesja gościa. Wszystkie aplikacje i dane z obecnej sesji zostaną usunięte."</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Zamknąć tryb gościa?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Wszystkie aplikacje i dane z obecnej sesji gościa zostaną usunięte."</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Wyjdź"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Zapisać aktywność gościa?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Możesz zapisać aktywność z obecnej sesji lub usunąć wszystkie aplikacje i dane"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Usuń"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Zapisz"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Zamknij tryb gościa"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Zresetuj sesję gościa"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Zakończ tryb gościa"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Cała aktywność zostanie usunięta po zamknięciu"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Możesz zapisać lub usunąć swoją aktywność podczas zamykania"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Zresetuj, aby usunąć aktywność w sesji w tym momencie. Możesz też ją zapisać lub usunąć podczas zamykania"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Zrób zdjęcie"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Wybierz obraz"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Wybierz zdjęcie"</string> diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml index a0355b9c419e..06faf68461ca 100644 --- a/packages/SettingsLib/res/values-pt-rBR/strings.xml +++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Redefinir"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Remover"</string> <string name="guest_resetting" msgid="7822120170191509566">"Redefinindo visitante…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Redefinir Sessão de visitante?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Essa ação vai iniciar uma nova Sessão de visitante e excluir todos os apps e dados da sessão atual"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Sair do modo visitante?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Essa ação vai excluir apps e dados da Sessão de visitante atual"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Sair"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Salvar a atividade do visitante?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Você pode salvar a atividade da sessão atual ou excluir todos os apps e dados"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Excluir"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Salvar"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Sair do modo visitante"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Redefinir Sessão de visitante"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Sair do modo visitante"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Todas as atividades serão excluídas ao sair"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Você pode salvar ou excluir sua atividade ao sair"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Faça uma redefinição para excluir a atividade da sessão agora. Você também pode salvar ou excluir a atividade ao sair"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Tirar uma foto"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Escolher uma imagem"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Selecionar foto"</string> diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml index 5b4172536a1f..4fc5728b4177 100644 --- a/packages/SettingsLib/res/values-pt-rPT/strings.xml +++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Repor"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Remover"</string> <string name="guest_resetting" msgid="7822120170191509566">"A repor o convidado…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Repor sessão de convidado?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Esta ação inicia uma nova sessão de convidado e elimina todas as apps e dados da sessão atual"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Sair do modo de convidado?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Esta ação elimina as apps e os dados da sessão de convidado atual"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Sair"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Guardar atividade de convidado?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Pode guardar a atividade da sessão atual ou eliminar todas as apps e dados"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Eliminar"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Guardar"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Sair do modo de convidado"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Repor sessão de convidado"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Sair do modo de convidado"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Toda a atividade é eliminada ao sair"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Pode guardar ou eliminar a sua atividade ao sair"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Reponha para eliminar agora a atividade da sessão. Em alternativa, pode guardar ou eliminar a atividade ao sair"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Tirar uma foto"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Escolher uma imagem"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Selecionar foto"</string> diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml index a0355b9c419e..06faf68461ca 100644 --- a/packages/SettingsLib/res/values-pt/strings.xml +++ b/packages/SettingsLib/res/values-pt/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Redefinir"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Remover"</string> <string name="guest_resetting" msgid="7822120170191509566">"Redefinindo visitante…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Redefinir Sessão de visitante?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Essa ação vai iniciar uma nova Sessão de visitante e excluir todos os apps e dados da sessão atual"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Sair do modo visitante?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Essa ação vai excluir apps e dados da Sessão de visitante atual"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Sair"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Salvar a atividade do visitante?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Você pode salvar a atividade da sessão atual ou excluir todos os apps e dados"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Excluir"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Salvar"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Sair do modo visitante"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Redefinir Sessão de visitante"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Sair do modo visitante"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Todas as atividades serão excluídas ao sair"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Você pode salvar ou excluir sua atividade ao sair"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Faça uma redefinição para excluir a atividade da sessão agora. Você também pode salvar ou excluir a atividade ao sair"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Tirar uma foto"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Escolher uma imagem"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Selecionar foto"</string> diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml index 9c7a2ce0dce6..ce00e55ade7c 100644 --- a/packages/SettingsLib/res/values-ro/strings.xml +++ b/packages/SettingsLib/res/values-ro/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Resetați"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Eliminați"</string> <string name="guest_resetting" msgid="7822120170191509566">"Se resetează invitatul…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Resetați sesiunea pentru invitați?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Astfel, va începe o nouă sesiune pentru invitați și se vor șterge toate aplicațiile și datele din sesiunea actuală"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Ieșiți din modul pentru invitați?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Se vor șterge toate aplicațiile și datele din sesiunea pentru invitați actuală"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Ieșiți"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Salvați activitatea invitatului?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Salvați activitatea din sesiunea actuală sau ștergeți aplicațiile și datele"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Ștergeți"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Salvați"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Ieșiți din modul pentru invitați"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Resetați sesiunea pentru invitați"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Ieșiți din modul pentru invitați"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Toate activitățile vor fi șterse la ieșire"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Puteți să salvați sau să ștergeți activitatea la ieșire"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Resetați pentru a șterge acum activitatea din sesiune sau salvați ori ștergeți activitatea la ieșire"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Faceți o fotografie"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Alegeți o imagine"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Selectați fotografia"</string> diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml index 3ce46e7bd0c1..2910ebc02652 100644 --- a/packages/SettingsLib/res/values-ru/strings.xml +++ b/packages/SettingsLib/res/values-ru/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Сбросить"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Удалить"</string> <string name="guest_resetting" msgid="7822120170191509566">"Сброс гостевого сеанса…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Сбросить гостевой сеанс?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"При этом начнется новый гостевой сеанс, а все данные и приложения предыдущего сеанса будут удалены."</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Выйти из гостевого режима?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Все приложения и данные текущего гостевого сеанса будут удалены."</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Выйти"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Сохранить историю сеанса?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Сохраните историю текущего сеанса или удалите данные и приложения."</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Удалить"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Сохранить"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Выйти из гостевого режима"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Сбросить гостевой сеанс"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Выйти из гостевого режима"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"История будет удалена сразу после выхода."</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"При выходе вы можете сохранить или удалить историю."</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Сбросьте историю сеанса прямо сейчас и удалите или сохраните ее при выходе."</string> <string name="user_image_take_photo" msgid="467512954561638530">"Сделать снимок"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Выбрать фото"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Выбрать фотографию"</string> diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml index 0cb9c840ee12..bd0caefe4786 100644 --- a/packages/SettingsLib/res/values-si/strings.xml +++ b/packages/SettingsLib/res/values-si/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"යළි සකසන්න"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"ඉවත් කරන්න"</string> <string name="guest_resetting" msgid="7822120170191509566">"අමුත්තා යළි සකසමින්…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"ආගන්තුක සැසිය යළි සකසන්නද?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"මෙය නව ආගන්තුක සැසියක් ආරම්භ කර වත්මන් සැසියෙන් සියලු යෙදුම් සහ දත්ත මකනු ඇත"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"ආගන්තුක ප්රකාරයෙන් පිටවන්නද?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"මෙය වත්මන් ආගන්තුක සැසියෙන් යෙදුම් සහ දත්ත මකනු ඇත"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"පිටවන්න"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"ආගන්තුක ක්රියාකාරකම් සුරකින්නද?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"ඔබට වත්මන් සැසියෙන් ක්රියාකාරකම් සුරැකීමට හෝ සියලු යෙදුම් සහ දත්ත මැකීමට හැකිය"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"මකන්න"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"සුරකින්න"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"ආගන්තුක ප්රකාරයෙන් පිටවන්න"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"ආගන්තුක සැසිය යළි සකසන්න"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"අමුත්තා පිටවීම"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"පිටවීමේදී සියලු ක්රියාකාරකම් මකනු ඇත"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"ඔබට පිටවීමේදී ඔබගේ ක්රියාකාරකම් සුරැකීමට හෝ මැකීමට හැකිය"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"දැන් සැසි ක්රියාකාරකම් මැකීමට යළි සකසන්න, නැතහොත් ඔබට පිටවීමේදී ක්රියාකාරකම් සුරැකීමට හෝ මැකීමට හැකිය"</string> <string name="user_image_take_photo" msgid="467512954561638530">"ඡායාරූපයක් ගන්න"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"රූපයක් තෝරන්න"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"ඡායාරූපය තෝරන්න"</string> diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml index 72a9f40ff5a6..c5f1f80e7ba5 100644 --- a/packages/SettingsLib/res/values-sk/strings.xml +++ b/packages/SettingsLib/res/values-sk/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Resetovať"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Odstrániť"</string> <string name="guest_resetting" msgid="7822120170191509566">"Relácia hosťa sa resetuje…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Chcete resetovať reláciu hosťa?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Týmto sa spustí nová relácia hosťa a odstránia sa všetky aplikácie a údaje z aktuálnej relácie"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Chcete skončiť režim pre hostí?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Ukončí sa režim pre hostí a odstránia sa aplikácie a údaje z relácie hosťa"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Ukončiť"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Chcete uložiť aktivitu hosťa?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Aktivitu v aktuálnej relácii uložte alebo odstráňte všetky aplikácie a údaje"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Odstrániť"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Uložiť"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Ukončiť režim pre hostí"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Resetovať reláciu hosťa"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Ukončiť režim pre hostí"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Pri ukončení sa všetka aktivita odstráni"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Aktivitu môžete pri ukončení uložiť alebo odstrániť"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Resetovaním ihneď odstráňte aktivitu relácie alebo ju uložte či odstráňte pri ukončení relácie"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Odfotiť"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Vybrať obrázok"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Vybrať fotku"</string> diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml index e49f0c4e5e02..a6e69e147750 100644 --- a/packages/SettingsLib/res/values-sl/strings.xml +++ b/packages/SettingsLib/res/values-sl/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Ponastavi"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Odstrani"</string> <string name="guest_resetting" msgid="7822120170191509566">"Ponastavljanje gosta …"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Želite ponastaviti sejo gosta?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"S tem boste začeli novo sejo gosta ter izbrisali vse aplikacije in podatke v trenutni seji."</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Zapri način za goste"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"S tem boste izbrisali aplikacije in podatke v trenutni seji gosta."</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Zapri"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Želite shraniti dejavnost gosta?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Lahko shranite dejavnost v trenutni seji ali izbrišete vse aplikacije in podatke."</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Izbriši"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Shrani"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Zapri način za goste"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Ponastavi sejo gosta"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Zapri sejo gosta"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Ko zaprete sejo, bo vsa dejavnost izbrisana."</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Ko zaprete sejo, lahko shranite ali izbrišete dejavnost."</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Ponastavite, če želite dejavnost v seji izbrisati zdaj, lahko pa jo shranite ali izbrišete, ko zaprete sejo."</string> <string name="user_image_take_photo" msgid="467512954561638530">"Fotografiranje"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Izberi sliko"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Izbira fotografije"</string> diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml index 9b62de269bb9..b1842b444a65 100644 --- a/packages/SettingsLib/res/values-sq/strings.xml +++ b/packages/SettingsLib/res/values-sq/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Rivendos"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Hiq"</string> <string name="guest_resetting" msgid="7822120170191509566">"Vizitori po rivendoset…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Të rivendoset sesioni për vizitorë?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Kjo do të fillojë një sesion të ri për vizitorë dhe do të fshijë të gjitha aplikacionet dhe të dhënat nga sesioni aktual"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Të hiqet modaliteti \"vizitor\"?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Kjo do të fshijë aplikacionet dhe të dhënat nga sesioni aktual për vizitorë"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Dil"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Të ruhet aktiviteti i vizitorit?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Ruaj aktivitetin nga sesioni aktual ose fshi të gjitha aplikacionet e të dhënat"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Fshi"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Ruaj"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Dil nga modaliteti \"vizitor\""</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Rivendos sesionin për vizitorë"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Dil nga modaliteti \"vizitor\""</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Të gjitha aktivitetet do të fshihen kur të dalësh"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Mund ta ruash ose ta fshish aktivitetin tënd kur të dalësh"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Rivendose për të fshirë aktivitetin e sesionit tani ose mund ta ruash ose ta fshish aktivitetin kur të dalësh"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Bëj një fotografi"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Zgjidh një imazh"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Zgjidh një fotografi"</string> diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml index eba79105f437..381cd971727e 100644 --- a/packages/SettingsLib/res/values-sr/strings.xml +++ b/packages/SettingsLib/res/values-sr/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Ресетуј"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Уклони"</string> <string name="guest_resetting" msgid="7822120170191509566">"Сесија госта се ресетује…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Желите да ресетујете сесију госта?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Тиме ћете покренути нову сесију госта и избрисати све апликације и податке из актуелне сесије"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Изаћи ћете из режима госта?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Тиме ћете избрисати све апликације и податке из актуелне сесије госта"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Изађи"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Сачуваћете активности госта?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Сачувајте активности из актуелне сесије или избришите све апликације и податке"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Избриши"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Сачувај"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Изађи из режима госта"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Ресетуј сесију госта"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Изађи из режима госта"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Све активности ће бити избрисане при излазу"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Можете да сачувате или избришете активности при излазу"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Ресетујете да бисте избрисали активности сесије одмах или можете да сачувате или избришете активности при излазу"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Сликај"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Одабери слику"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Изаберите слику"</string> diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml index 1c1c38fc193b..683619a6a305 100644 --- a/packages/SettingsLib/res/values-sv/strings.xml +++ b/packages/SettingsLib/res/values-sv/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Återställ"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Ta bort"</string> <string name="guest_resetting" msgid="7822120170191509566">"Gästsessionen återställs …"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Vill du återställa gästsessionen?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"En ny gästsession startas och alla appar och all data från den pågående sessionen raderas"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Vill du avsluta gästläget?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Appar och data från den pågående gästsessionen raderas"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Avsluta"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Vill du spara gästaktivitet?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Du kan spara aktivitet från den pågående sessionen eller radera appar och data"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Radera"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Spara"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Avsluta gästläget"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Återställ gästsession"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Avsluta gästsession"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"All aktivitet raderas när du avslutar"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Du kan spara eller radera aktivitet när du avslutar"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Återställ om du vill radera sessionsaktiviteten nu. Du kan också spara eller radera aktivitet när du avslutar"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Ta ett foto"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Välj en bild"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Välj foto"</string> diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml index fd7c893f0998..69ab95d7dc51 100644 --- a/packages/SettingsLib/res/values-sw/strings.xml +++ b/packages/SettingsLib/res/values-sw/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Badilisha"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Ondoa"</string> <string name="guest_resetting" msgid="7822120170191509566">"Inabadilisha kipindi cha mgeni…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Ungependa kuweka upya kipindi cha mgeni?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Hii itaanzisha upya kipindi cha mgeni na kufuta programu na data yote kwenye kipindi cha sasa"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Utafunga matumizi ya wageni?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Hatua hii itafuta programu na data kutoka kwenye kipindi cha mgeni cha sasa"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Funga"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Utahifadhi shughuli za mgeni?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Unaweza kuhifadhi shughuli kutoka kipindi cha sasa au kufuta programu na data yote"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Futa"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Hifadhi"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Funga matumizi ya wageni"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Weka upya kipindi cha mgeni"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Funga utumiaji wa mgeni"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Shughuli zote zitafutwa wakati wa kufunga"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Unaweza kuhifadhi au kufuta shughuli zako wakati wa kufunga"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Weka upya ili ufute shughuli za kipindi sasa au unaweza kuhifadhi au kufuta shughuli wakati wa kufunga"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Piga picha"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Chagua picha"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Chagua picha"</string> diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml index 236b74bfcb57..6544a2335b18 100644 --- a/packages/SettingsLib/res/values-ta/strings.xml +++ b/packages/SettingsLib/res/values-ta/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"மீட்டமை"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"அகற்று"</string> <string name="guest_resetting" msgid="7822120170191509566">"கெஸ்ட்டை மீட்டமைக்கிறது…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"கெஸ்ட் அமர்வை ரீசெட் செய்யவா?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"புதிய கெஸ்ட் அமர்வு தொடங்கப்படும், மேலும் தற்போதைய கெஸ்ட் அமர்வின் ஆப்ஸ் மற்றும் தரவு அனைத்தும் நீக்கப்படும்"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"கெஸ்ட் முறையிலிருந்து வெளியேறவா?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"தற்போதைய கெஸ்ட் அமர்வின் ஆப்ஸ் மற்றும் தரவு அனைத்தும் நீக்கப்படும்"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"வெளியேறு"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"கெஸ்ட் செயல்பாடுகளைச் சேமிக்கவா?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"தற்போதைய அமர்வின் செயல்பாடுகளைச் சேமிக்கலாம் அல்லது ஆப்ஸையும் தரவையும் நீக்கலாம்"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"நீக்கு"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"சேமி"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"கெஸ்ட் பயன்முறையிலிருந்து வெளியேறு"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"கெஸ்ட் அமர்வை ரீசெட் செய்"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"கெஸ்ட் பயன்முறையிலிருந்து வெளியேறு"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"வெளியேறியவுடன் அனைத்துச் செயல்பாடுகளும் நீக்கப்படும்"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"வெளியேறும்போது செயல்பாடுகளைச் சேமிக்கலாம் அல்லது நீக்கலாம்"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"அமர்வின் செயல்பாடுகளை இப்போதே நீக்க ரீசெட் செய்யவும் அல்லது வெளியேறும்போது செயல்பாடுகளைச் சேமிக்கலாம் அல்லது நீக்கலாம்"</string> <string name="user_image_take_photo" msgid="467512954561638530">"படமெடுங்கள்"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"படத்தைத் தேர்வுசெய்யுங்கள்"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"படத்தைத் தேர்ந்தெடுங்கள்"</string> diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml index 187e1794de93..f6612b8243dd 100644 --- a/packages/SettingsLib/res/values-te/strings.xml +++ b/packages/SettingsLib/res/values-te/strings.xml @@ -95,7 +95,7 @@ <string name="bluetooth_disconnecting" msgid="7638892134401574338">"డిస్కనెక్ట్ చేస్తోంది..."</string> <string name="bluetooth_connecting" msgid="5871702668260192755">"కనెక్ట్ చేస్తోంది..."</string> <string name="bluetooth_connected" msgid="8065345572198502293">"కనెక్ట్ చేయబడిన<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> - <string name="bluetooth_pairing" msgid="4269046942588193600">"జత చేస్తోంది..."</string> + <string name="bluetooth_pairing" msgid="4269046942588193600">"పెయిరింగ్..."</string> <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"కనెక్ట్ చేయబడింది (ఫోన్ కాదు)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> <string name="bluetooth_connected_no_a2dp" msgid="8566874395813947092">"కనెక్ట్ చేయబడింది (మీడియా కాదు)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> <string name="bluetooth_connected_no_map" msgid="3381860077002724689">"కనెక్ట్ చేయబడింది (సందేశ యాక్సెస్ లేదు)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> @@ -594,10 +594,25 @@ <string name="guest_exit_guest" msgid="5908239569510734136">"గెస్ట్ను తీసివేయండి"</string> <string name="guest_reset_guest" msgid="6110013010356013758">"గెస్ట్ సెషన్ను రీసెట్ చేయండి"</string> <string name="guest_reset_guest_dialog_title" msgid="8047270010895437534">"గెస్ట్ సెషన్ను రీసెట్ చేయాలా?"</string> - <string name="guest_remove_guest_dialog_title" msgid="4548511006624088072">"అతిథిని తీసివేయాలా?"</string> + <string name="guest_remove_guest_dialog_title" msgid="4548511006624088072">"గెస్ట్ను తీసివేయాలా?"</string> <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"రీసెట్ చేయండి"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"తీసివేయండి"</string> <string name="guest_resetting" msgid="7822120170191509566">"గెస్ట్ సెషన్ను రీసెట్ చేస్తోంది…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"గెస్ట్ సెషన్ను రీసెట్ చేయాలా?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"ఇది కొత్త గెస్ట్ సెషన్ను ప్రారంభిస్తుంది, ప్రస్తుత సెషన్ నుండి అన్ని యాప్లు, డేటాను తొలగించండి"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"గెస్ట్ మోడ్ నిష్క్రమించాలా?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"ఇది ప్రస్తుత గెస్ట్ సెషన్ నుండి యాప్లు, డేటాను తొలగిస్తుంది"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"నిష్క్రమించండి"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"గెస్ట్ యాక్టివిటీని సేవ్ చేయాలా?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"మీరు సెషన్ నుండి యాక్టివిటీని సేవ్ చేయవచ్చు, అన్ని యాప్లు, డేటాను తొలగించవచ్చు"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"తొలగించండి"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"సేవ్ చేయండి"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"గెస్ట్ మోడ్ నుండి నిష్క్రమణ"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"గెస్ట్ సెషన్ను రీసెట్ చేయండి"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"గెస్ట్ మోడ్ నుండి నిష్క్రమించండి"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"నిష్క్రమణ సమయంలో మొత్తం యాక్టివిటీ తొలగించబడుతుంది"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"మీ నిష్క్రమణలో, యాక్టివిటీని సేవ్ చేయవచ్చు లేదా తొలగించవచ్చు"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"సెషన్ యాక్టివిటీని తొలగించడానికి ఇప్పుడే రీసెట్ చేయండి లేదా మీరు నిష్క్రమించేటప్పుడు యాక్టివిటీని సేవ్ చేయవచ్చు లేదా తొలగించవచ్చు"</string> <string name="user_image_take_photo" msgid="467512954561638530">"ఒక ఫోటో తీయండి"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"ఇమేజ్ను ఎంచుకోండి"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"ఫోటోను ఎంచుకోండి"</string> diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml index 41ef1e41b90f..c9b99038398c 100644 --- a/packages/SettingsLib/res/values-th/strings.xml +++ b/packages/SettingsLib/res/values-th/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"รีเซ็ต"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"นำออก"</string> <string name="guest_resetting" msgid="7822120170191509566">"กำลังรีเซ็ตผู้เข้าร่วม…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"รีเซ็ตเซสชันผู้มาเยือนไหม"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"การดำเนินการนี้จะเริ่มเซสชันผู้มาเยือนใหม่ และจะลบแอปและข้อมูลทั้งหมดจากเซสชันปัจจุบัน"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"ออกจากโหมดผู้มาเยือนไหม"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"การดำเนินการนี้จะลบแอปและข้อมูลออกจากเซสชันผู้มาเยือนในปัจจุบัน"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"ออก"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"บันทึกกิจกรรมของผู้มาเยือนไหม"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"คุณสามารถบันทึกกิจกรรมจากเซสชันปัจจุบันหรือจะลบแอปและข้อมูลทั้งหมดก็ได้"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"ลบ"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"บันทึก"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"ออกจากโหมดผู้มาเยือน"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"รีเซ็ตเซสชันผู้มาเยือน"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"ออกจากโหมดผู้มาเยือน"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"ระบบจะลบกิจกรรมทั้งหมดเมื่อออก"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"คุณสามารถบันทึกหรือลบกิจกรรมเมื่อออก"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"รีเซ็ตเพื่อลบกิจกรรมของเซสชันตอนนี้เลย หรือจะบันทึกหรือลบกิจกรรมเมื่อออกก็ได้"</string> <string name="user_image_take_photo" msgid="467512954561638530">"ถ่ายรูป"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"เลือกรูปภาพ"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"เลือกรูปภาพ"</string> diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml index 7d4a4b49bc0d..a1c4fffc0217 100644 --- a/packages/SettingsLib/res/values-tl/strings.xml +++ b/packages/SettingsLib/res/values-tl/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"I-reset"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Alisin"</string> <string name="guest_resetting" msgid="7822120170191509566">"Nire-reset ang bisita…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"I-reset ang session ng bisita?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Magsisimula ito ng bagong session ng bisita at made-delete ang lahat ng app at data mula sa kasalukuyang session"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Umalis sa guest mode?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Ide-delete nito ang mga app at data mula sa kasalukuyang session ng bisita"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Umalis"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"I-save ang aktibidad ng bisita?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Puwedeng i-save ang aktibidad ng session ngayon o i-delete lahat ng app at data"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"I-delete"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"I-save"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Umalis sa guest mode"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"I-reset ang session ng bisita"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Umalis sa pagiging bisita"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Made-delete ang lahat ng aktibidad kapag umalis"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Puwede mong i-save o i-delete ang aktibidad pagkaalis"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Mag-reset para mag-delete ng aktibidad ng session ngayon, o puwede kang mag-save o mag-delete ng aktibidad pagkaalis"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Kumuha ng larawan"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Pumili ng larawan"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Pumili ng larawan"</string> diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml index 5e5b42756043..fada83b37ff8 100644 --- a/packages/SettingsLib/res/values-tr/strings.xml +++ b/packages/SettingsLib/res/values-tr/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Sıfırla"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Kaldır"</string> <string name="guest_resetting" msgid="7822120170191509566">"Misafir oturumu sıfırlanıyor…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Misafir oturumu sıfırlansın mı?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Bu işlem, yeni bir misafir oturumu başlatarak mevcut oturumdaki tüm uygulamaları ve verileri siler"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Misafir modundan çıkılsın mı?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Bu işlem mevcut misafir oturumundaki tüm uygulamaları ve verileri siler"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Çık"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Misafir etkinliği kaydedilsin mi?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Oturumdaki etkinliği kaydedebilir ya da tüm uygulama ve verileri silebilirsiniz"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Sil"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Kaydet"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Misafir modundan çık"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Misafir oturumunu sıfırla"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Misafir modundan çık"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Çıkış yapıldığında tüm etkinlikler silinir"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Etkinliklerinizi çıkarken kaydedebilir veya silebilirsiniz"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Oturum etkinliklerini hemen silmek için sıfırlayın. Etkinlikleri çıkarken kaydetmeyi veya silmeyi de tercih edebilirsiniz"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Fotoğraf çek"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Resim seç"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Fotoğraf seç"</string> diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml index b068670f8036..b0d65507db99 100644 --- a/packages/SettingsLib/res/values-uk/strings.xml +++ b/packages/SettingsLib/res/values-uk/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Скинути"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Вилучити"</string> <string name="guest_resetting" msgid="7822120170191509566">"Скидання сеансу в режимі \"Гість\"…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Скинути сеанс у режимі гостя?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Почнеться новий сеанс у режимі гостя, а всі додатки й дані з поточного сеансу буде видалено"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Вийти з режиму гостя?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Усі додатки й дані з поточного сеансу в режимі гостя буде видалено."</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Вийти"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Зберегти дії в режимі гостя?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Ви можете зберегти дії з поточного сеансу або видалити всі додатки й дані"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Видалити"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Зберегти"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Вийти з режиму гостя"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Скинути сеанс у режимі гостя"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Вийти з режиму гостя"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Під час виходу буде видалено всі дії"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Під час виходу можна зберегти або видалити ваші дії"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Скиньте, щоб зараз видалити дії під час сеансу. Ви також можете зберегти чи видалити дії під час виходу."</string> <string name="user_image_take_photo" msgid="467512954561638530">"Зробити фотографію"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Вибрати зображення"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Вибрати фотографію"</string> diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml index 1386e05985b5..e2586bebe25a 100644 --- a/packages/SettingsLib/res/values-ur/strings.xml +++ b/packages/SettingsLib/res/values-ur/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"ری سیٹ کریں"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"ہٹائیں"</string> <string name="guest_resetting" msgid="7822120170191509566">"مہمان کو ری سیٹ کرنا…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"مہمان سیشن کو ری سیٹ کریں؟"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"یہ ایک نیا مہمان سیشن شروع کرے گا اور موجودہ سیشن سے تمام ایپس اور ڈیٹا کو حذف کر دے گا"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"مہمان وضع سے باہر نکلیں؟"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"یہ موجودہ مہمان سیشن سے ایپس اور ڈیٹا کو حذف کر دے گا"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"باہر نکلیں"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"مہمان کی سرگرمی محفوظ کریں؟"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"آپ موجودہ سیشن سے سرگرمی کو محفوظ یا تمام ایپس اور ڈیٹا کو حذف کر سکتے ہیں"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"حذف کریں"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"محفوظ کریں"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"مہمان وضع سے باہر نکلیں"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"مہمان سیشن کو ری سیٹ کریں"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"مہمان وضع سے باہر نکلیں"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"باہر نکلنے پر تمام سرگرمیاں حذف کر دی جائیں گی"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"باہر نکلنے پر آپ اپنی سرگرمی کو محفوظ یا حذف کر سکتے ہیں"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"سیشن کی سرگرمی کو ابھی حذف کرنے کے لیے ری سیٹ کریں، یا باہر نکلنے پر آپ اپنی سرگرمی کو محفوظ یا حذف کر سکتے ہیں"</string> <string name="user_image_take_photo" msgid="467512954561638530">"ایک تصویر لیں"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"ایک تصویر منتخب کریں"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"تصویر منتخب کریں"</string> diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml index 52cc9cbd7c03..19500f8ad6ca 100644 --- a/packages/SettingsLib/res/values-uz/strings.xml +++ b/packages/SettingsLib/res/values-uz/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Tiklash"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Olib tashlash"</string> <string name="guest_resetting" msgid="7822120170191509566">"Mehmon seansi tiklanmoqda…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Mehmon seansi tiklansinmi?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Bunda yangi mehmon seansi ishga tushadi va joriy seans ilova va maʼlumotlari tozalanadi"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Mehmon rejimidan chiqasizmi?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Bunda joriy mehmon seansidagi ilova va ularning maʼlumotlari tozalanadi"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Chiqish"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Mehmon faoliyati saqlansinmi?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Joriy seansdagi faoliyatni saqlash yoki barcha ilova va maʼlumotlarni tozalash mumkin"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Oʻchirish"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Saqlash"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Mehmon rejimidan chiqish"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Mehmon seansini tiklash"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Mehmon rejimidan chiqish"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Chiqish vaqtida faoliyat butunlay tozalanadi"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Chiqish vaqtida faoliyatni saqlash yoki tozalash mumkin"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Faoliyat hozir tozalanib tiklanishi yoki chiqish vaqtida saqlanishi yoki tozalanishi mumkin"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Suratga olish"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Rasm tanlash"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Surat tanlash"</string> diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml index 1965942b82e8..904d2a4afeab 100644 --- a/packages/SettingsLib/res/values-vi/strings.xml +++ b/packages/SettingsLib/res/values-vi/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Đặt lại"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Xoá"</string> <string name="guest_resetting" msgid="7822120170191509566">"Đang đặt lại phiên khách…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Đặt lại phiên khách?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Thao tác này sẽ bắt đầu một phiên khách mới và xoá mọi ứng dụng cũng như dữ liệu trong phiên hiện tại"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Thoát khỏi chế độ khách?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Thao tác này sẽ xoá các ứng dụng và dữ liệu trong phiên khách hiện tại"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Thoát"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Lưu hoạt động ở chế độ khách?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Bạn có thể lưu hoạt động trong phiên hiện tại hoặc xoá mọi ứng dụng và dữ liệu"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Xoá"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Lưu"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Thoát khỏi chế độ khách"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Đặt lại phiên khách"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Thoát khỏi chế độ khách"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Mọi hoạt động sẽ bị xoá khi thoát"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Bạn có thể lưu hoặc xoá hoạt động của mình khi thoát"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Đặt lại để xoá hoạt động trong phiên ngay bây giờ, hoặc bạn có thể lưu hoặc xoá hoạt động khi thoát"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Chụp ảnh"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Chọn một hình ảnh"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Chọn ảnh"</string> diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml index 9bb725a119d9..a6f738f0ac1d 100644 --- a/packages/SettingsLib/res/values-zh-rCN/strings.xml +++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"重置"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"移除"</string> <string name="guest_resetting" msgid="7822120170191509566">"正在重置访客会话…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"要重置访客会话吗?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"此操作会开始新的访客会话,并删除当前会话中的所有应用和数据"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"要退出访客模式吗?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"此操作会删除当前访客会话中的所有应用和数据"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"退出"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"要保存访客活动记录吗?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"您可以保存当前会话中的活动记录,也可以删除所有应用和数据"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"删除"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"保存"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"退出访客模式"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"重置访客会话"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"退出访客模式"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"系统会在退出时删除所有活动记录"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"您可以在退出时保存或删除您的活动记录"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"请立即重置以删除会话活动记录;或者,您也可以在退出时保存或删除活动记录"</string> <string name="user_image_take_photo" msgid="467512954561638530">"拍摄照片"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"选择图片"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"选择照片"</string> diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml index 726827cc1054..471b53ef7723 100644 --- a/packages/SettingsLib/res/values-zh-rHK/strings.xml +++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"重設"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"移除"</string> <string name="guest_resetting" msgid="7822120170191509566">"正在重設訪客…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"要重設訪客工作階段嗎?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"此操作會開始新的訪客工作階段,並刪除目前工作階段中的所有應用程式和活動"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"要結束訪客模式嗎?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"此操作會刪除目前訪客工作階段中的所有應用程式和資料"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"結束"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"要儲存訪客活動嗎?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"您可儲存目前工作階段中的活動或刪除所有應用程式和資料"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"刪除"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"儲存"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"結束訪客模式"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"重設訪客工作階段"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"結束訪客模式"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"結束時將會刪除所有活動"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"您可以在結束時儲存或刪除活動"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"重設即可立即刪除工作階段活動,或在結束時儲存或刪除工作階段"</string> <string name="user_image_take_photo" msgid="467512954561638530">"拍照"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"選擇圖片"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"揀相"</string> diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml index f77e88905743..9a4cc5b66a06 100644 --- a/packages/SettingsLib/res/values-zh-rTW/strings.xml +++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"重設"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"移除"</string> <string name="guest_resetting" msgid="7822120170191509566">"正在重設訪客…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"要重設訪客工作階段嗎?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"這麼做將開始新的訪客工作階段,並刪除目前工作階段中的所有應用程式和資料"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"要結束訪客模式嗎?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"這麼做將刪除目前訪客工作階段中的所有應用程式和資料"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"結束"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"要儲存訪客活動嗎?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"你可以儲存目前工作階段中的活動,也可以刪除所有應用程式和資料"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"刪除"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"儲存"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"結束訪客模式"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"重設訪客工作階段"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"結束訪客模式"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"結束時將刪除所有活動"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"你可以在結束時儲存或刪除活動"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"重設即可立即刪除工作階段活動,你也可以在結束時儲存或刪除活動"</string> <string name="user_image_take_photo" msgid="467512954561638530">"拍照"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"選擇圖片"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"選取相片"</string> diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml index 1cb1fa443e15..45c4d6748d02 100644 --- a/packages/SettingsLib/res/values-zu/strings.xml +++ b/packages/SettingsLib/res/values-zu/strings.xml @@ -598,6 +598,21 @@ <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"Setha kabusha"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"Susa"</string> <string name="guest_resetting" msgid="7822120170191509566">"Ukusetha kabusha isimenywa…"</string> + <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"Sesha kabusha isikhathi sesihambeli?"</string> + <string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Lokhu kuzoqala isikhathi sesihambeli esisha futhi kusule wonke ama-app nedatha kusuka esikhathini samanje"</string> + <string name="guest_exit_dialog_title" msgid="1846494656849381804">"Phuma kumodi yesihambeli?"</string> + <string name="guest_exit_dialog_message" msgid="1743218864242719783">"Lokhu kuzosula ama-app nedatha kusuka esikhathini sesihambeli samanje"</string> + <string name="guest_exit_dialog_button" msgid="1736401897067442044">"Phuma"</string> + <string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Londoloza umsebenzi wesihambeli?"</string> + <string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Ungalondoloza umsebenzi kusuka esikhathini samanje noma usule wonke ama-app nedatha"</string> + <string name="guest_exit_clear_data_button" msgid="3425812652180679014">"Sula"</string> + <string name="guest_exit_save_data_button" msgid="3690974510644963547">"Londoloza"</string> + <string name="guest_exit_button" msgid="5774985819191803960">"Phuma kumodi yesivakashi"</string> + <string name="guest_reset_button" msgid="2515069346223503479">"Setha kabusha isikhathi sesihambeli"</string> + <string name="guest_exit_quick_settings_button" msgid="1912362095913765471">"Phuma kusivakashi"</string> + <string name="guest_notification_ephemeral" msgid="7263252466950923871">"Wonke umsebenzi uzosulwa lapho uphuma"</string> + <string name="guest_notification_non_ephemeral" msgid="6843799963012259330">"Ungalondoloza noma usule umsebenzi wakho lapho uphuma"</string> + <string name="guest_notification_non_ephemeral_non_first_login" msgid="8009307983766934876">"Setha kabusha ukuze usule umsebenzi wesikhathi manje, noma ungalondoloza noma usule umsebenzi lapho uphuma"</string> <string name="user_image_take_photo" msgid="467512954561638530">"Thatha isithombe"</string> <string name="user_image_choose_photo" msgid="1363820919146782908">"Khetha isithombe"</string> <string name="user_image_photo_selector" msgid="433658323306627093">"Khetha isithombe"</string> diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index df2685db17f5..8ef712a8f7a0 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -1438,6 +1438,44 @@ <string name="guest_remove_guest_confirm_button">Remove</string> <!-- Status message indicating the device is in the process of resetting the guest user. [CHAR_LIMIT=NONE] --> <string name="guest_resetting">Resetting guest\u2026</string> + <!-- Dialog title on action reset and restart guest [CHAR LIMIT=60] --> + <string name="guest_reset_and_restart_dialog_title">Reset guest session?</string> + <!-- Dialog message on action reset and restart guest [CHAR LIMIT=160] --> + <string name="guest_reset_and_restart_dialog_message">This will start a new guest + session and delete all apps and data from the current session</string> + <!-- Dialog title on action exit guest (ephemeral guest) [CHAR LIMIT=32] --> + <string name="guest_exit_dialog_title">Exit guest mode?</string> + <!-- Dialog message on action exit guest (ephemeral guest) [CHAR LIMIT=80] --> + <string name="guest_exit_dialog_message">This will delete + apps and data from the current guest session</string> + <!-- Dialog button on action exit guest (ephemeral guest) [CHAR LIMIT=80] --> + <string name="guest_exit_dialog_button">Exit</string> + <!-- Dialog title on action exit guest (non-ephemeral guest) [CHAR LIMIT=32] --> + <string name="guest_exit_dialog_title_non_ephemeral">Save guest activity?</string> + <!-- Dialog message on action exit guest (non-ephemeral guest) [CHAR LIMIT=80] --> + <string name="guest_exit_dialog_message_non_ephemeral">You can save activity from + the current session or delete all apps and data</string> + <!-- Button on guest exit, clear data (non-ephemeral guest) [CHAR LIMIT=80] --> + <string name="guest_exit_clear_data_button">Delete</string> + <!-- Button on guest exit, save data (non-ephemeral guest) [CHAR LIMIT=80] --> + <string name="guest_exit_save_data_button">Save</string> + <!-- Label for button in confirmation dialog when exiting guest user [CHAR LIMIT=35] --> + <string name="guest_exit_button">Exit guest mode</string> + <!-- Label for button in confirmation dialog when resetting guest user [CHAR LIMIT=35] --> + <string name="guest_reset_button">Reset guest session</string> + <!-- Label for guest icon in quick settings user switcher [CHAR LIMIT=35] --> + <string name="guest_exit_quick_settings_button">Exit guest</string> + <!-- Message of the notification when guest mode is entered + and it's a ephemeral guest [CHAR LIMIT=60] --> + <string name="guest_notification_ephemeral">All activity will be deleted on exit</string> + <!-- Message of the notification when guest mode is entered + and it's not a ephemeral guest and it's a first time guest login [CHAR LIMIT=60] --> + <string name="guest_notification_non_ephemeral">You can save or delete your activity on exit</string> + <!-- Message of the notification when guest mode is entered + and it's not a ephemeral guest and it's not a first time guest login [CHAR LIMIT=NONE] --> + <string name="guest_notification_non_ephemeral_non_first_login">Reset to delete session + activity now, or you can save or delete activity on exit</string> + <!-- An option in a photo selection dialog to take a new photo [CHAR LIMIT=50] --> <string name="user_image_take_photo">Take a photo</string> <!-- An option in a photo selection dialog to choose a pre-existing image [CHAR LIMIT=50] --> diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/EditUserInfoControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/EditUserInfoControllerTest.java index f28572f5f71d..69484ed527b5 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/EditUserInfoControllerTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/EditUserInfoControllerTest.java @@ -37,9 +37,9 @@ import android.widget.ImageView; import androidx.fragment.app.FragmentActivity; import com.android.settingslib.R; +import com.android.settingslib.RestrictedLockUtils; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Answers; @@ -55,7 +55,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; @RunWith(RobolectricTestRunner.class) -@Ignore public class EditUserInfoControllerTest { private static final int MAX_USER_NAME_LENGTH = 100; @@ -87,6 +86,11 @@ public class EditUserInfoControllerTest { } @Override + RestrictedLockUtils.EnforcedAdmin getChangePhotoAdminRestriction(Context context) { + return null; + } + + @Override boolean isChangePhotoRestrictedByBase(Context context) { return mPhotoRestrictedByBase; } @@ -98,7 +102,7 @@ public class EditUserInfoControllerTest { mActivity = spy(ActivityController.of(new FragmentActivity()).get()); mActivity.setTheme(R.style.Theme_AppCompat_DayNight); mController = new TestEditUserInfoController(); - mPhotoRestrictedByBase = true; + mPhotoRestrictedByBase = false; } @Test @@ -262,7 +266,7 @@ public class EditUserInfoControllerTest { @Test public void createDialog_canNotChangePhoto_nullPhotoController() { - mPhotoRestrictedByBase = false; + mPhotoRestrictedByBase = true; mController.createDialog(mActivity, mActivityStarter, mCurrentIcon, "test", "title", null, null); diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java index acb33c356a8b..75068cbcbb4b 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java @@ -317,6 +317,9 @@ public class GlobalSettingsValidators { VALIDATORS.put(Global.USER_PREFERRED_RESOLUTION_WIDTH, ANY_INTEGER_VALIDATOR); VALIDATORS.put(Global.Wearable.WET_MODE_ON, BOOLEAN_VALIDATOR); VALIDATORS.put(Global.Wearable.COOLDOWN_MODE_ON, BOOLEAN_VALIDATOR); + VALIDATORS.put(Global.Wearable.TOUCH_AND_HOLD_WATCH_FACE, BOOLEAN_VALIDATOR); + VALIDATORS.put(Global.Wearable.SCREEN_UNLOCK_SOUND_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Global.Wearable.CHARGING_SOUNDS_ENABLED, BOOLEAN_VALIDATOR); } } diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index 077337cdc8c3..700c04cf34ec 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -5220,7 +5220,7 @@ public class SettingsProvider extends ContentProvider { .getResources() .getBoolean(R.bool.def_wearable_hotwordDetectionEnabled)); initGlobalSettingsDefaultValForWearLocked( - Global.Wearable.SMART_REPLIES_ENABLED, false); + Global.Wearable.SMART_REPLIES_ENABLED, true); Setting locationMode = getSecureSettingsLocked(userId).getSettingLocked(Secure.LOCATION_MODE); initGlobalSettingsDefaultValForWearLocked( diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java index f1b23d5733af..17f731446a5a 100644 --- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java @@ -422,6 +422,7 @@ public class SettingsBackupTest { Settings.Global.RADIO_NFC, Settings.Global.RADIO_WIFI, Settings.Global.RADIO_WIMAX, + Settings.Global.REMOVE_GUEST_ON_EXIT, Settings.Global.RECOMMENDED_NETWORK_EVALUATOR_CACHE_EXPIRY_MS, Settings.Global.READ_EXTERNAL_STORAGE_ENFORCED_DEFAULT, Settings.Global.RESTRICTED_NETWORKING_MODE, @@ -663,7 +664,9 @@ public class SettingsBackupTest { Settings.Global.Wearable.CLOCKWORK_LONG_PRESS_TO_ASSISTANT_ENABLED, Settings.Global.Wearable.WEAR_ACTIVITY_AUTO_RESUME_TIMEOUT_SET_BY_USER, Settings.Global.Wearable.WET_MODE_ON, - Settings.Global.Wearable.COOLDOWN_MODE_ON); + Settings.Global.Wearable.COOLDOWN_MODE_ON, + Settings.Global.Wearable.TOUCH_AND_HOLD_WATCH_FACE, + Settings.Global.Wearable.SCREEN_UNLOCK_SOUND_ENABLED); private static final Set<String> BACKUP_DENY_LIST_SECURE_SETTINGS = newHashSet( diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 3b862ffbbd9e..4ec0ba0544fd 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -683,12 +683,15 @@ <!-- Permission required for CTS test - CtsAppEnumerationTestCases --> <uses-permission android:name="android.permission.MAKE_UID_VISIBLE" /> - <!-- Permission required for CTS test - CtsKeystoreTestCases --> - <uses-permission android:name="android.permission.REQUEST_UNIQUE_ID_ATTESTATION" /> + <!-- Permission required for CTS test - CtsInputTestCases --> + <uses-permission android:name="android.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY" /> <!-- Permission required for CTS test - CtsDevicePolicyManagerTestCases --> <uses-permission android:name="android.permission.READ_NEARBY_STREAMING_POLICY" /> + <!-- Permission required for CTS test - CtsKeystoreTestCases --> + <uses-permission android:name="android.permission.REQUEST_UNIQUE_ID_ATTESTATION" /> + <application android:label="@string/app_label" android:theme="@android:style/Theme.DeviceDefault.DayNight" android:defaultToDeviceProtectedStorage="true" diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java index 1ce4c64fd8b8..68679c794c35 100644 --- a/packages/Shell/src/com/android/shell/BugreportProgressService.java +++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java @@ -572,6 +572,7 @@ public class BugreportProgressService extends Service { break; case INTENT_BUGREPORT_DONE: maybeShowWarningMessageAndCloseNotification(id); + break; case INTENT_BUGREPORT_CANCEL: cancel(id); break; @@ -843,16 +844,11 @@ public class BugreportProgressService extends Service { PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT); } - @GuardedBy("mLock") - private void stopProgressLocked(int id) { - stopProgressLocked(id, /* cancelNotification */ true); - } - /** * Finalizes the progress on a given bugreport and cancel its notification. */ @GuardedBy("mLock") - private void stopProgressLocked(int id, boolean cancelNotification) { + private void stopProgressLocked(int id) { if (mBugreportInfos.indexOfKey(id) < 0) { Log.w(TAG, "ID not watched: " + id); } else { @@ -862,12 +858,10 @@ public class BugreportProgressService extends Service { // Must stop foreground service first, otherwise notif.cancel() will fail below. stopForegroundWhenDoneLocked(id); - if (cancelNotification) { - Log.d(TAG, "stopProgress(" + id + "): cancel notification"); - NotificationManager.from(mContext).cancel(id); - } else { - Log.d(TAG, "stopProgress(" + id + ")"); - } + + Log.d(TAG, "stopProgress(" + id + "): cancel notification"); + NotificationManager.from(mContext).cancel(id); + stopSelfWhenDoneLocked(); } @@ -1112,30 +1106,7 @@ public class BugreportProgressService extends Service { return; } - if (mIsWatch) { - // Wear wants to send the notification directly and not wait for the user to tap on the - // notification. - triggerShareBugreportAndLocalNotification(info); - } else { - triggerLocalNotification(info); - } - } - - /** - * Responsible for starting the bugerport sharing process and posting a notification which - * shows that the bugreport has been taken and that the sharing process has kicked-off. - */ - private void triggerShareBugreportAndLocalNotification(final BugreportInfo info) { - boolean isPlainText = info.bugreportFile.getName().toLowerCase().endsWith(".txt"); - if (!isPlainText) { - // Already zipped, share it right away. - shareBugreport(info.id, info, /* showWarning */ false, - /* cancelNotificationWhenStoppingProgress */ false); - sendBugreportNotification(info, mTakingScreenshot); - } else { - // Asynchronously zip the file first, then share it. - shareAndPostNotificationForZippedBugreport(info, mTakingScreenshot); - } + triggerLocalNotification(info); } /** @@ -1249,16 +1220,14 @@ public class BugreportProgressService extends Service { } private void shareBugreport(int id, BugreportInfo sharedInfo) { - shareBugreport(id, sharedInfo, !hasUserDecidedNotToGetWarningMessage(), - /* cancelNotificationWhenStoppingProgress */ true); + shareBugreport(id, sharedInfo, !hasUserDecidedNotToGetWarningMessage()); } /** * Shares the bugreport upon user's request by issuing a {@link Intent#ACTION_SEND_MULTIPLE} * intent, but issuing a warning dialog the first time. */ - private void shareBugreport(int id, BugreportInfo sharedInfo, boolean showWarning, - boolean cancelNotificationWhenStoppingProgress) { + private void shareBugreport(int id, BugreportInfo sharedInfo, boolean showWarning) { MetricsLogger.action(this, MetricsEvent.ACTION_BUGREPORT_NOTIFICATION_ACTION_SHARE); BugreportInfo info; synchronized (mLock) { @@ -1307,7 +1276,7 @@ public class BugreportProgressService extends Service { } synchronized (mLock) { // ... and stop watching this process. - stopProgressLocked(id, cancelNotificationWhenStoppingProgress); + stopProgressLocked(id); } } @@ -1362,7 +1331,7 @@ public class BugreportProgressService extends Service { PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE)) .setDeleteIntent(newCancelIntent(mContext, info)); } else { - // Device is a watch. + // Device is a watch if (hasUserDecidedNotToGetWarningMessage()) { // No action button needed for the notification. User can swipe to dimiss. builder.setActions(new Action[0]); @@ -1433,24 +1402,6 @@ public class BugreportProgressService extends Service { } /** - * Zips a bugreport, shares it, and sends for it a bugreport notification. - */ - private void shareAndPostNotificationForZippedBugreport(final BugreportInfo info, - final boolean takingScreenshot) { - new AsyncTask<Void, Void, Void>() { - @Override - protected Void doInBackground(Void... params) { - Looper.prepare(); - zipBugreport(info); - shareBugreport(info.id, info, /* showWarning */ false, - /* cancelNotificationWhenStoppingProgress */ false); - sendBugreportNotification(info, mTakingScreenshot); - return null; - } - }.execute(); - } - - /** * Zips a bugreport file, returning the path to the new file (or to the * original in case of failure). */ diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp index f05c1e2e76f2..de9e1f4ccec5 100644 --- a/packages/SystemUI/Android.bp +++ b/packages/SystemUI/Android.bp @@ -125,6 +125,7 @@ android_library { ], manifest: "AndroidManifest.xml", + javacflags: ["-Adagger.fastInit=enabled"], kotlincflags: ["-Xjvm-default=enable"], plugins: ["dagger2-compiler"], diff --git a/packages/SystemUI/res-keyguard/drawable/qs_auto_rotate_icon_off.xml b/packages/SystemUI/res-keyguard/drawable/qs_auto_rotate_icon_off.xml new file mode 100644 index 000000000000..538f3284a301 --- /dev/null +++ b/packages/SystemUI/res-keyguard/drawable/qs_auto_rotate_icon_off.xml @@ -0,0 +1,725 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + ~ 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. + --> + +<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <target android:name="_R_G_L_2_G_T_1"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="28" + android:propertyName="translateX" + android:startOffset="0" + android:valueFrom="7.062" + android:valueTo="8.578" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="221" + android:propertyName="translateX" + android:startOffset="28" + android:valueFrom="8.578" + android:valueTo="-1.789" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="418" + android:propertyName="translateX" + android:startOffset="248" + android:valueFrom="-1.789" + android:valueTo="-7" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.1,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_2_G_T_1"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="28" + android:propertyName="translateY" + android:startOffset="0" + android:valueFrom="3.312" + android:valueTo="2.016" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="221" + android:propertyName="translateY" + android:startOffset="28" + android:valueFrom="2.016" + android:valueTo="-8.789" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="418" + android:propertyName="translateY" + android:startOffset="248" + android:valueFrom="-8.789" + android:valueTo="-3.5" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.1,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_2_G_T_1"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="28" + android:propertyName="rotation" + android:startOffset="0" + android:valueFrom="180" + android:valueTo="90" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="166" + android:propertyName="rotation" + android:startOffset="28" + android:valueFrom="90" + android:valueTo="90" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="55" + android:propertyName="rotation" + android:startOffset="193" + android:valueFrom="90" + android:valueTo="0" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_2_G_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="250" + android:propertyName="rotation" + android:startOffset="0" + android:valueFrom="-135" + android:valueTo="-180" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_1_G_T_1"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="28" + android:propertyName="translateX" + android:startOffset="0" + android:valueFrom="-7" + android:valueTo="-8.859" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="221" + android:propertyName="translateX" + android:startOffset="28" + android:valueFrom="-8.859" + android:valueTo="1.69" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="418" + android:propertyName="translateX" + android:startOffset="248" + android:valueFrom="1.69" + android:valueTo="7" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.1,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_1_G_T_1"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="28" + android:propertyName="translateY" + android:startOffset="0" + android:valueFrom="-3.594" + android:valueTo="-1.922" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="221" + android:propertyName="translateY" + android:startOffset="28" + android:valueFrom="-1.922" + android:valueTo="8.627" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="418" + android:propertyName="translateY" + android:startOffset="248" + android:valueFrom="8.627" + android:valueTo="3.5" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.1,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_1_G_T_1"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="28" + android:propertyName="rotation" + android:startOffset="0" + android:valueFrom="360" + android:valueTo="270" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="166" + android:propertyName="rotation" + android:startOffset="28" + android:valueFrom="270" + android:valueTo="270" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="55" + android:propertyName="rotation" + android:startOffset="193" + android:valueFrom="270" + android:valueTo="180" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="418" + android:propertyName="rotation" + android:startOffset="248" + android:valueFrom="180" + android:valueTo="180" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0 0.1,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_1_G_N_1_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="250" + android:propertyName="rotation" + android:startOffset="0" + android:valueFrom="-135" + android:valueTo="-180" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G_D_0_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="28" + android:propertyName="pathData" + android:startOffset="0" + android:valueFrom="M8.52 3.53 C8.52,3.53 2.94,9.08 2.94,9.08 C2.3,9.72 1.27,9.74 0.65,9.12 C0.65,9.12 -7.53,0.95 -7.53,0.95 C-7.53,0.95 -4.7,0.94 -4.7,0.94 C-4.7,0.94 1.78,7.42 1.78,7.42 C1.78,7.42 7.11,2.11 7.11,2.11 C7.11,2.11 7.14,2.14 7.14,2.14 C7.14,2.14 8.48,3.49 8.48,3.49 C8.48,3.49 8.5,3.51 8.5,3.51 C8.5,3.51 8.52,3.53 8.52,3.53c " + android:valueTo="M8.82 3.18 C8.26,3.74 2.94,9.08 2.94,9.08 C2.3,9.72 1.27,9.74 0.65,9.12 C0.65,9.12 -6.08,2.36 -6.08,2.36 C-6.08,2.36 -4.7,0.94 -4.7,0.94 C-4.7,0.94 1.78,7.42 1.78,7.42 C1.78,7.42 7.5,1.77 7.5,1.77 C7.5,1.77 7.49,1.78 7.49,1.78 C7.49,1.78 8.87,0.41 8.87,0.41 C8.87,0.41 8.95,0.5 9.05,0.58 C9.86,1.4 9.7,2.29 8.82,3.18c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="66" + android:propertyName="pathData" + android:startOffset="28" + android:valueFrom="M8.82 3.18 C8.26,3.74 2.94,9.08 2.94,9.08 C2.3,9.72 1.27,9.74 0.65,9.12 C0.65,9.12 -6.08,2.36 -6.08,2.36 C-6.08,2.36 -4.7,0.94 -4.7,0.94 C-4.7,0.94 1.78,7.42 1.78,7.42 C1.78,7.42 7.5,1.77 7.5,1.77 C7.5,1.77 7.49,1.78 7.49,1.78 C7.49,1.78 8.87,0.41 8.87,0.41 C8.87,0.41 8.95,0.5 9.05,0.58 C9.86,1.4 9.7,2.29 8.82,3.18c " + android:valueTo="M8.82 3.18 C8.26,3.74 2.94,9.08 2.94,9.08 C2.3,9.72 1.27,9.74 0.65,9.12 C0.65,9.12 -2.78,5.89 -2.78,5.89 C-2.78,5.89 -1.29,4.47 -1.29,4.47 C-1.29,4.47 1.78,7.42 1.78,7.42 C1.78,7.42 7.5,1.77 7.5,1.77 C7.5,1.77 4.54,-1.11 4.54,-1.11 C4.54,-1.11 5.95,-2.51 5.95,-2.51 C5.95,-2.51 8.36,-0.12 9.05,0.58 C9.86,1.4 9.7,2.29 8.82,3.18c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="72" + android:propertyName="pathData" + android:startOffset="94" + android:valueFrom="M8.82 3.18 C8.26,3.74 2.94,9.08 2.94,9.08 C2.3,9.72 1.27,9.74 0.65,9.12 C0.65,9.12 -2.78,5.89 -2.78,5.89 C-2.78,5.89 -1.29,4.47 -1.29,4.47 C-1.29,4.47 1.78,7.42 1.78,7.42 C1.78,7.42 7.5,1.77 7.5,1.77 C7.5,1.77 4.54,-1.11 4.54,-1.11 C4.54,-1.11 5.95,-2.51 5.95,-2.51 C5.95,-2.51 8.36,-0.12 9.05,0.58 C9.86,1.4 9.7,2.29 8.82,3.18c " + android:valueTo="M8.82 3.18 C8.26,3.74 2.94,9.08 2.94,9.08 C2.3,9.72 1.27,9.74 0.65,9.12 C0.65,9.12 0.36,8.83 0.36,8.83 C0.36,8.83 1.8,7.44 1.8,7.44 C1.8,7.44 1.78,7.42 1.78,7.42 C1.78,7.42 7.5,1.77 7.5,1.77 C7.5,1.77 4.54,-1.11 4.54,-1.11 C4.54,-1.11 5.95,-2.51 5.95,-2.51 C5.95,-2.51 8.36,-0.12 9.05,0.58 C9.86,1.4 9.7,2.29 8.82,3.18c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="28" + android:propertyName="pathData" + android:startOffset="166" + android:valueFrom="M8.82 3.18 C8.26,3.74 2.94,9.08 2.94,9.08 C2.3,9.72 1.27,9.74 0.65,9.12 C0.65,9.12 0.36,8.83 0.36,8.83 C0.36,8.83 1.8,7.44 1.8,7.44 C1.8,7.44 1.78,7.42 1.78,7.42 C1.78,7.42 7.5,1.77 7.5,1.77 C7.5,1.77 4.54,-1.11 4.54,-1.11 C4.54,-1.11 5.95,-2.51 5.95,-2.51 C5.95,-2.51 8.36,-0.12 9.05,0.58 C9.86,1.4 9.7,2.29 8.82,3.18c " + android:valueTo="M8.82 3.18 C8.26,3.74 3.22,8.8 3.22,8.8 C3.22,8.8 3.21,8.79 3.21,8.79 C3.21,8.79 3.24,8.8 3.24,8.8 C3.24,8.8 1.8,7.44 1.8,7.44 C1.8,7.44 1.78,7.42 1.78,7.42 C1.78,7.42 7.5,1.77 7.5,1.77 C7.5,1.77 4.54,-1.11 4.54,-1.11 C4.54,-1.11 5.95,-2.51 5.95,-2.51 C5.95,-2.51 8.36,-0.12 9.05,0.58 C9.86,1.4 9.7,2.29 8.82,3.18c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="55" + android:propertyName="pathData" + android:startOffset="193" + android:valueFrom="M8.82 3.18 C8.26,3.74 3.22,8.8 3.22,8.8 C3.22,8.8 3.21,8.79 3.21,8.79 C3.21,8.79 3.24,8.8 3.24,8.8 C3.24,8.8 1.8,7.44 1.8,7.44 C1.8,7.44 1.78,7.42 1.78,7.42 C1.78,7.42 7.5,1.77 7.5,1.77 C7.5,1.77 4.54,-1.11 4.54,-1.11 C4.54,-1.11 5.95,-2.51 5.95,-2.51 C5.95,-2.51 8.36,-0.12 9.05,0.58 C9.86,1.4 9.7,2.29 8.82,3.18c " + android:valueTo="M8.82 3.18 C8.26,3.74 5.82,6.14 5.82,6.14 C5.82,6.14 5.81,6.14 5.81,6.14 C5.81,6.14 5.83,6.14 5.83,6.14 C5.83,6.14 4.39,4.78 4.39,4.78 C4.39,4.78 4.37,4.76 4.37,4.76 C4.37,4.76 7.5,1.77 7.5,1.77 C7.5,1.77 4.54,-1.11 4.54,-1.11 C4.54,-1.11 5.95,-2.51 5.95,-2.51 C5.95,-2.51 8.36,-0.12 9.05,0.58 C9.86,1.4 9.7,2.29 8.82,3.18c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="41" + android:propertyName="pathData" + android:startOffset="248" + android:valueFrom="M8.82 3.18 C8.26,3.74 5.82,6.14 5.82,6.14 C5.82,6.14 5.81,6.14 5.81,6.14 C5.81,6.14 5.83,6.14 5.83,6.14 C5.83,6.14 4.39,4.78 4.39,4.78 C4.39,4.78 4.37,4.76 4.37,4.76 C4.37,4.76 7.5,1.77 7.5,1.77 C7.5,1.77 4.54,-1.11 4.54,-1.11 C4.54,-1.11 5.95,-2.51 5.95,-2.51 C5.95,-2.51 8.36,-0.12 9.05,0.58 C9.86,1.4 9.7,2.29 8.82,3.18c " + android:valueTo="M8.91 3.09 C8.91,3.09 8.91,3.1 8.91,3.1 C8.91,3.1 8.9,3.09 8.9,3.09 C8.9,3.09 7.49,1.74 7.49,1.74 C7.49,1.74 7.5,1.75 7.5,1.75 C7.5,1.75 7.48,1.73 7.48,1.73 C7.48,1.73 7.5,1.77 7.5,1.77 C7.5,1.77 4.54,-1.11 4.54,-1.11 C4.54,-1.11 5.95,-2.51 5.95,-2.51 C5.95,-2.51 8.36,-0.12 9.05,0.58 C9.86,1.4 9.79,2.2 8.91,3.09c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="28" + android:propertyName="pathData" + android:startOffset="290" + android:valueFrom="M8.91 3.09 C8.91,3.09 8.91,3.1 8.91,3.1 C8.91,3.1 8.9,3.09 8.9,3.09 C8.9,3.09 7.49,1.74 7.49,1.74 C7.49,1.74 7.5,1.75 7.5,1.75 C7.5,1.75 7.48,1.73 7.48,1.73 C7.48,1.73 7.5,1.77 7.5,1.77 C7.5,1.77 4.54,-1.11 4.54,-1.11 C4.54,-1.11 5.95,-2.51 5.95,-2.51 C5.95,-2.51 8.36,-0.12 9.05,0.58 C9.86,1.4 9.79,2.2 8.91,3.09c " + android:valueTo="M9.05 0.57 C9.05,0.57 9.05,0.58 9.05,0.58 C9.05,0.58 9.04,0.57 9.04,0.57 C9.04,0.57 7.6,1.83 7.6,1.83 C7.6,1.83 7.61,1.85 7.61,1.85 C7.61,1.85 7.59,1.83 7.59,1.83 C7.59,1.83 7.61,1.86 7.61,1.86 C7.61,1.86 4.54,-1.11 4.54,-1.11 C4.54,-1.11 5.95,-2.51 5.95,-2.51 C5.95,-2.51 9.05,0.58 9.05,0.58 C9.05,0.58 9.05,0.57 9.05,0.57c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="83" + android:propertyName="pathData" + android:startOffset="317" + android:valueFrom="M9.05 0.57 C9.05,0.57 9.05,0.58 9.05,0.58 C9.05,0.58 9.04,0.57 9.04,0.57 C9.04,0.57 7.6,1.83 7.6,1.83 C7.6,1.83 7.61,1.85 7.61,1.85 C7.61,1.85 7.59,1.83 7.59,1.83 C7.59,1.83 7.61,1.86 7.61,1.86 C7.61,1.86 4.54,-1.11 4.54,-1.11 C4.54,-1.11 5.95,-2.51 5.95,-2.51 C5.95,-2.51 9.05,0.58 9.05,0.58 C9.05,0.58 9.05,0.57 9.05,0.57c " + android:valueTo="M5.94 -2.52 C5.94,-2.52 5.94,-2.51 5.94,-2.51 C5.94,-2.51 5.93,-2.52 5.93,-2.52 C5.93,-2.52 4.53,-1.12 4.53,-1.12 C4.53,-1.12 4.55,-1.11 4.55,-1.11 C4.55,-1.11 4.53,-1.13 4.53,-1.13 C4.53,-1.13 4.55,-1.09 4.55,-1.09 C4.55,-1.09 4.54,-1.11 4.54,-1.11 C4.54,-1.11 5.95,-2.51 5.95,-2.51 C5.95,-2.51 5.94,-2.52 5.94,-2.52 C5.94,-2.52 5.94,-2.52 5.94,-2.52c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.1,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G_D_1_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="28" + android:propertyName="pathData" + android:startOffset="0" + android:valueFrom="M-8.52 -3.53 C-8.52,-3.53 -2.94,-9.08 -2.94,-9.08 C-2.3,-9.72 -1.27,-9.74 -0.65,-9.12 C-0.65,-9.12 7.53,-0.95 7.53,-0.95 C7.53,-0.95 4.7,-0.94 4.7,-0.94 C4.7,-0.94 -1.78,-7.42 -1.78,-7.42 C-1.78,-7.42 -7.11,-2.11 -7.11,-2.11 C-7.11,-2.11 -7.14,-2.14 -7.14,-2.14 C-7.14,-2.14 -8.48,-3.49 -8.48,-3.49 C-8.48,-3.49 -8.5,-3.51 -8.5,-3.51 C-8.5,-3.51 -8.52,-3.53 -8.52,-3.53c " + android:valueTo="M-8.82 -3.18 C-8.26,-3.74 -2.94,-9.08 -2.94,-9.08 C-2.3,-9.72 -1.27,-9.74 -0.65,-9.12 C-0.65,-9.12 6.08,-2.36 6.08,-2.36 C6.08,-2.36 4.7,-0.94 4.7,-0.94 C4.7,-0.94 -1.78,-7.42 -1.78,-7.42 C-1.78,-7.42 -7.5,-1.77 -7.5,-1.77 C-7.5,-1.77 -7.49,-1.78 -7.49,-1.78 C-7.49,-1.78 -8.87,-0.41 -8.87,-0.41 C-8.87,-0.41 -8.95,-0.5 -9.05,-0.58 C-9.86,-1.4 -9.7,-2.29 -8.82,-3.18c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="66" + android:propertyName="pathData" + android:startOffset="28" + android:valueFrom="M-8.82 -3.18 C-8.26,-3.74 -2.94,-9.08 -2.94,-9.08 C-2.3,-9.72 -1.27,-9.74 -0.65,-9.12 C-0.65,-9.12 6.08,-2.36 6.08,-2.36 C6.08,-2.36 4.7,-0.94 4.7,-0.94 C4.7,-0.94 -1.78,-7.42 -1.78,-7.42 C-1.78,-7.42 -7.5,-1.77 -7.5,-1.77 C-7.5,-1.77 -7.49,-1.78 -7.49,-1.78 C-7.49,-1.78 -8.87,-0.41 -8.87,-0.41 C-8.87,-0.41 -8.95,-0.5 -9.05,-0.58 C-9.86,-1.4 -9.7,-2.29 -8.82,-3.18c " + android:valueTo="M-8.82 -3.18 C-8.26,-3.74 -2.94,-9.08 -2.94,-9.08 C-2.3,-9.72 -1.27,-9.74 -0.65,-9.12 C-0.65,-9.12 2.78,-5.89 2.78,-5.89 C2.78,-5.89 1.29,-4.47 1.29,-4.47 C1.29,-4.47 -1.78,-7.42 -1.78,-7.42 C-1.78,-7.42 -7.5,-1.77 -7.5,-1.77 C-7.5,-1.77 -4.54,1.11 -4.54,1.11 C-4.54,1.11 -5.95,2.51 -5.95,2.51 C-5.95,2.51 -8.36,0.12 -9.05,-0.58 C-9.86,-1.4 -9.7,-2.29 -8.82,-3.18c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="72" + android:propertyName="pathData" + android:startOffset="94" + android:valueFrom="M-8.82 -3.18 C-8.26,-3.74 -2.94,-9.08 -2.94,-9.08 C-2.3,-9.72 -1.27,-9.74 -0.65,-9.12 C-0.65,-9.12 2.78,-5.89 2.78,-5.89 C2.78,-5.89 1.29,-4.47 1.29,-4.47 C1.29,-4.47 -1.78,-7.42 -1.78,-7.42 C-1.78,-7.42 -7.5,-1.77 -7.5,-1.77 C-7.5,-1.77 -4.54,1.11 -4.54,1.11 C-4.54,1.11 -5.95,2.51 -5.95,2.51 C-5.95,2.51 -8.36,0.12 -9.05,-0.58 C-9.86,-1.4 -9.7,-2.29 -8.82,-3.18c " + android:valueTo="M-8.82 -3.18 C-8.26,-3.74 -2.94,-9.08 -2.94,-9.08 C-2.3,-9.72 -1.27,-9.74 -0.65,-9.12 C-0.65,-9.12 -0.36,-8.83 -0.36,-8.83 C-0.36,-8.83 -1.8,-7.44 -1.8,-7.44 C-1.8,-7.44 -1.78,-7.42 -1.78,-7.42 C-1.78,-7.42 -7.5,-1.77 -7.5,-1.77 C-7.5,-1.77 -4.54,1.11 -4.54,1.11 C-4.54,1.11 -5.95,2.51 -5.95,2.51 C-5.95,2.51 -8.36,0.12 -9.05,-0.58 C-9.86,-1.4 -9.7,-2.29 -8.82,-3.18c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="28" + android:propertyName="pathData" + android:startOffset="166" + android:valueFrom="M-8.82 -3.18 C-8.26,-3.74 -2.94,-9.08 -2.94,-9.08 C-2.3,-9.72 -1.27,-9.74 -0.65,-9.12 C-0.65,-9.12 -0.36,-8.83 -0.36,-8.83 C-0.36,-8.83 -1.8,-7.44 -1.8,-7.44 C-1.8,-7.44 -1.78,-7.42 -1.78,-7.42 C-1.78,-7.42 -7.5,-1.77 -7.5,-1.77 C-7.5,-1.77 -4.54,1.11 -4.54,1.11 C-4.54,1.11 -5.95,2.51 -5.95,2.51 C-5.95,2.51 -8.36,0.12 -9.05,-0.58 C-9.86,-1.4 -9.7,-2.29 -8.82,-3.18c " + android:valueTo="M-8.82 -3.18 C-8.26,-3.74 -3.22,-8.8 -3.22,-8.8 C-3.22,-8.8 -3.21,-8.79 -3.21,-8.79 C-3.21,-8.79 -3.24,-8.8 -3.24,-8.8 C-3.24,-8.8 -1.8,-7.44 -1.8,-7.44 C-1.8,-7.44 -1.78,-7.42 -1.78,-7.42 C-1.78,-7.42 -7.5,-1.77 -7.5,-1.77 C-7.5,-1.77 -4.54,1.11 -4.54,1.11 C-4.54,1.11 -5.95,2.51 -5.95,2.51 C-5.95,2.51 -8.36,0.12 -9.05,-0.58 C-9.86,-1.4 -9.7,-2.29 -8.82,-3.18c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="55" + android:propertyName="pathData" + android:startOffset="193" + android:valueFrom="M-8.82 -3.18 C-8.26,-3.74 -3.22,-8.8 -3.22,-8.8 C-3.22,-8.8 -3.21,-8.79 -3.21,-8.79 C-3.21,-8.79 -3.24,-8.8 -3.24,-8.8 C-3.24,-8.8 -1.8,-7.44 -1.8,-7.44 C-1.8,-7.44 -1.78,-7.42 -1.78,-7.42 C-1.78,-7.42 -7.5,-1.77 -7.5,-1.77 C-7.5,-1.77 -4.54,1.11 -4.54,1.11 C-4.54,1.11 -5.95,2.51 -5.95,2.51 C-5.95,2.51 -8.36,0.12 -9.05,-0.58 C-9.86,-1.4 -9.7,-2.29 -8.82,-3.18c " + android:valueTo="M-8.82 -3.18 C-8.26,-3.74 -5.81,-6.14 -5.81,-6.14 C-5.81,-6.14 -5.81,-6.13 -5.81,-6.13 C-5.81,-6.13 -5.83,-6.14 -5.83,-6.14 C-5.83,-6.14 -4.39,-4.78 -4.39,-4.78 C-4.39,-4.78 -4.37,-4.76 -4.37,-4.76 C-4.37,-4.76 -7.5,-1.77 -7.5,-1.77 C-7.5,-1.77 -4.54,1.11 -4.54,1.11 C-4.54,1.11 -5.95,2.51 -5.95,2.51 C-5.95,2.51 -8.36,0.12 -9.05,-0.58 C-9.86,-1.4 -9.7,-2.29 -8.82,-3.18c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="41" + android:propertyName="pathData" + android:startOffset="248" + android:valueFrom="M-8.82 -3.18 C-8.26,-3.74 -5.81,-6.14 -5.81,-6.14 C-5.81,-6.14 -5.81,-6.13 -5.81,-6.13 C-5.81,-6.13 -5.83,-6.14 -5.83,-6.14 C-5.83,-6.14 -4.39,-4.78 -4.39,-4.78 C-4.39,-4.78 -4.37,-4.76 -4.37,-4.76 C-4.37,-4.76 -7.5,-1.77 -7.5,-1.77 C-7.5,-1.77 -4.54,1.11 -4.54,1.11 C-4.54,1.11 -5.95,2.51 -5.95,2.51 C-5.95,2.51 -8.36,0.12 -9.05,-0.58 C-9.86,-1.4 -9.7,-2.29 -8.82,-3.18c " + android:valueTo="M-8.91 -3.09 C-8.91,-3.09 -8.91,-3.09 -8.91,-3.09 C-8.91,-3.09 -8.9,-3.09 -8.9,-3.09 C-8.9,-3.09 -7.49,-1.74 -7.49,-1.74 C-7.49,-1.74 -7.5,-1.75 -7.5,-1.75 C-7.5,-1.75 -7.48,-1.73 -7.48,-1.73 C-7.48,-1.73 -7.5,-1.77 -7.5,-1.77 C-7.5,-1.77 -4.54,1.11 -4.54,1.11 C-4.54,1.11 -5.95,2.51 -5.95,2.51 C-5.95,2.51 -8.36,0.12 -9.05,-0.58 C-9.86,-1.4 -9.79,-2.2 -8.91,-3.09c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="28" + android:propertyName="pathData" + android:startOffset="290" + android:valueFrom="M-8.91 -3.09 C-8.91,-3.09 -8.91,-3.09 -8.91,-3.09 C-8.91,-3.09 -8.9,-3.09 -8.9,-3.09 C-8.9,-3.09 -7.49,-1.74 -7.49,-1.74 C-7.49,-1.74 -7.5,-1.75 -7.5,-1.75 C-7.5,-1.75 -7.48,-1.73 -7.48,-1.73 C-7.48,-1.73 -7.5,-1.77 -7.5,-1.77 C-7.5,-1.77 -4.54,1.11 -4.54,1.11 C-4.54,1.11 -5.95,2.51 -5.95,2.51 C-5.95,2.51 -8.36,0.12 -9.05,-0.58 C-9.86,-1.4 -9.79,-2.2 -8.91,-3.09c " + android:valueTo="M-9.05 -0.57 C-9.05,-0.57 -9.05,-0.58 -9.05,-0.58 C-9.05,-0.58 -9.04,-0.57 -9.04,-0.57 C-9.04,-0.57 -7.59,-1.83 -7.59,-1.83 C-7.59,-1.83 -7.61,-1.85 -7.61,-1.85 C-7.61,-1.85 -7.59,-1.83 -7.59,-1.83 C-7.59,-1.83 -7.61,-1.86 -7.61,-1.86 C-7.61,-1.86 -4.54,1.11 -4.54,1.11 C-4.54,1.11 -5.95,2.51 -5.95,2.51 C-5.95,2.51 -9.05,-0.58 -9.05,-0.58 C-9.05,-0.58 -9.05,-0.57 -9.05,-0.57c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="83" + android:propertyName="pathData" + android:startOffset="317" + android:valueFrom="M-9.05 -0.57 C-9.05,-0.57 -9.05,-0.58 -9.05,-0.58 C-9.05,-0.58 -9.04,-0.57 -9.04,-0.57 C-9.04,-0.57 -7.59,-1.83 -7.59,-1.83 C-7.59,-1.83 -7.61,-1.85 -7.61,-1.85 C-7.61,-1.85 -7.59,-1.83 -7.59,-1.83 C-7.59,-1.83 -7.61,-1.86 -7.61,-1.86 C-7.61,-1.86 -4.54,1.11 -4.54,1.11 C-4.54,1.11 -5.95,2.51 -5.95,2.51 C-5.95,2.51 -9.05,-0.58 -9.05,-0.58 C-9.05,-0.58 -9.05,-0.57 -9.05,-0.57c " + android:valueTo="M-5.94 2.52 C-5.94,2.52 -5.94,2.51 -5.94,2.51 C-5.94,2.51 -5.93,2.52 -5.93,2.52 C-5.93,2.52 -4.53,1.12 -4.53,1.12 C-4.53,1.12 -4.55,1.11 -4.55,1.11 C-4.55,1.11 -4.53,1.13 -4.53,1.13 C-4.53,1.13 -4.55,1.09 -4.55,1.09 C-4.55,1.09 -4.54,1.11 -4.54,1.11 C-4.54,1.11 -5.95,2.51 -5.95,2.51 C-5.95,2.51 -5.94,2.52 -5.94,2.52 C-5.94,2.52 -5.94,2.52 -5.94,2.52c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.1,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G_D_2_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="61" + android:propertyName="pathData" + android:startOffset="0" + android:valueFrom="M7.54 -0.94 C7.54,-0.94 7.54,-0.95 7.54,-0.95 C7.55,-0.94 7.54,-0.94 7.55,-0.94 C7.55,-0.94 7.53,-0.94 7.53,-0.94 C7.53,-0.94 7.52,-0.94 7.52,-0.94 C7.52,-0.94 7.54,-0.94 7.54,-0.94 C7.54,-0.94 7.52,-0.94 7.52,-0.94 C7.52,-0.94 7.54,-0.94 7.54,-0.94c " + android:valueTo="M7.54 -0.94 C7.54,-0.94 7.54,-0.95 7.54,-0.95 C7.55,-0.94 7.54,-0.94 7.55,-0.94 C7.55,-0.94 7.53,-0.94 7.53,-0.94 C7.53,-0.94 7.52,-0.94 7.52,-0.94 C7.52,-0.94 7.54,-0.94 7.54,-0.94 C7.54,-0.94 7.52,-0.94 7.52,-0.94 C7.52,-0.94 7.54,-0.94 7.54,-0.94c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="28" + android:propertyName="pathData" + android:startOffset="61" + android:valueFrom="M7.54 -0.94 C7.54,-0.94 7.54,-0.95 7.54,-0.95 C7.55,-0.94 7.54,-0.94 7.55,-0.94 C7.55,-0.94 7.53,-0.94 7.53,-0.94 C7.53,-0.94 7.52,-0.94 7.52,-0.94 C7.52,-0.94 7.54,-0.94 7.54,-0.94 C7.54,-0.94 7.52,-0.94 7.52,-0.94 C7.52,-0.94 7.54,-0.94 7.54,-0.94c " + android:valueTo="M6.15 -2.35 C6.15,-2.35 6.15,-2.35 6.15,-2.35 C6.16,-2.34 6.15,-2.35 6.16,-2.35 C6.16,-2.35 7.53,-0.94 7.53,-0.94 C7.53,-0.94 4.7,-0.94 4.7,-0.94 C4.7,-0.94 4.72,-0.93 4.72,-0.93 C4.72,-0.93 4.7,-0.94 4.7,-0.94 C4.7,-0.94 6.15,-2.35 6.15,-2.35c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="143" + android:propertyName="pathData" + android:startOffset="88" + android:valueFrom="M6.15 -2.35 C6.15,-2.35 6.15,-2.35 6.15,-2.35 C6.16,-2.34 6.15,-2.35 6.16,-2.35 C6.16,-2.35 7.53,-0.94 7.53,-0.94 C7.53,-0.94 4.7,-0.94 4.7,-0.94 C4.7,-0.94 4.72,-0.93 4.72,-0.93 C4.72,-0.93 4.7,-0.94 4.7,-0.94 C4.7,-0.94 6.15,-2.35 6.15,-2.35c " + android:valueTo="M-0.65 -9.12 C-0.65,-9.12 -0.66,-9.13 -0.66,-9.13 C-0.65,-9.12 -0.66,-9.12 -0.65,-9.12 C-0.65,-9.12 7.53,-0.94 7.53,-0.94 C7.53,-0.94 4.7,-0.94 4.7,-0.94 C4.7,-0.94 -1.78,-7.42 -1.78,-7.42 C-1.78,-7.42 -1.8,-7.43 -1.8,-7.43 C-1.8,-7.43 -0.65,-9.12 -0.65,-9.12c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="17" + android:propertyName="pathData" + android:startOffset="232" + android:valueFrom="M-0.65 -9.12 C-0.65,-9.12 -0.66,-9.13 -0.66,-9.13 C-0.65,-9.12 -0.66,-9.12 -0.65,-9.12 C-0.65,-9.12 7.53,-0.94 7.53,-0.94 C7.53,-0.94 4.7,-0.94 4.7,-0.94 C4.7,-0.94 -1.78,-7.42 -1.78,-7.42 C-1.78,-7.42 -1.8,-7.43 -1.8,-7.43 C-1.8,-7.43 -0.65,-9.12 -0.65,-9.12c " + android:valueTo="M-3.21 -8.85 C-3.21,-8.85 -2.94,-9.08 -2.94,-9.08 C-2.3,-9.72 -1.27,-9.74 -0.65,-9.12 C-0.65,-9.12 7.53,-0.94 7.53,-0.94 C7.53,-0.94 4.7,-0.94 4.7,-0.94 C4.7,-0.94 -1.78,-7.42 -1.78,-7.42 C-1.78,-7.42 -1.8,-7.43 -1.8,-7.43 C-1.8,-7.43 -3.21,-8.85 -3.21,-8.85c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="418" + android:propertyName="pathData" + android:startOffset="248" + android:valueFrom="M-3.21 -8.85 C-3.21,-8.85 -2.94,-9.08 -2.94,-9.08 C-2.3,-9.72 -1.27,-9.74 -0.65,-9.12 C-0.65,-9.12 7.53,-0.94 7.53,-0.94 C7.53,-0.94 4.7,-0.94 4.7,-0.94 C4.7,-0.94 -1.78,-7.42 -1.78,-7.42 C-1.78,-7.42 -1.8,-7.43 -1.8,-7.43 C-1.8,-7.43 -3.21,-8.85 -3.21,-8.85c " + android:valueTo="M-8.52 -3.53 C-8.52,-3.53 -2.94,-9.08 -2.94,-9.08 C-2.3,-9.72 -1.27,-9.74 -0.65,-9.12 C-0.65,-9.12 7.53,-0.94 7.53,-0.94 C7.53,-0.94 4.7,-0.94 4.7,-0.94 C4.7,-0.94 -1.78,-7.42 -1.78,-7.42 C-1.78,-7.42 -7.11,-2.11 -7.11,-2.11 C-7.11,-2.11 -8.52,-3.53 -8.52,-3.53c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.1,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G_D_3_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="61" + android:propertyName="pathData" + android:startOffset="0" + android:valueFrom="M-7.54 0.94 C-7.54,0.94 -7.54,0.95 -7.54,0.95 C-7.55,0.94 -7.54,0.94 -7.54,0.94 C-7.54,0.94 -7.53,0.94 -7.53,0.94 C-7.53,0.94 -7.52,0.94 -7.52,0.94 C-7.52,0.94 -7.54,0.94 -7.54,0.94 C-7.54,0.94 -7.52,0.94 -7.52,0.94 C-7.52,0.94 -7.54,0.94 -7.54,0.94c " + android:valueTo="M-7.54 0.94 C-7.54,0.94 -7.54,0.95 -7.54,0.95 C-7.55,0.94 -7.54,0.94 -7.54,0.94 C-7.54,0.94 -7.53,0.94 -7.53,0.94 C-7.53,0.94 -7.52,0.94 -7.52,0.94 C-7.52,0.94 -7.54,0.94 -7.54,0.94 C-7.54,0.94 -7.52,0.94 -7.52,0.94 C-7.52,0.94 -7.54,0.94 -7.54,0.94c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="28" + android:propertyName="pathData" + android:startOffset="61" + android:valueFrom="M-7.54 0.94 C-7.54,0.94 -7.54,0.95 -7.54,0.95 C-7.55,0.94 -7.54,0.94 -7.54,0.94 C-7.54,0.94 -7.53,0.94 -7.53,0.94 C-7.53,0.94 -7.52,0.94 -7.52,0.94 C-7.52,0.94 -7.54,0.94 -7.54,0.94 C-7.54,0.94 -7.52,0.94 -7.52,0.94 C-7.52,0.94 -7.54,0.94 -7.54,0.94c " + android:valueTo="M-6.15 2.35 C-6.15,2.35 -6.15,2.35 -6.15,2.35 C-6.16,2.34 -6.15,2.35 -6.15,2.35 C-6.15,2.35 -6.14,2.36 -6.14,2.36 C-6.14,2.36 -4.7,0.94 -4.7,0.94 C-4.7,0.94 -4.72,0.93 -4.72,0.93 C-4.72,0.93 -4.7,0.94 -4.7,0.94 C-4.7,0.94 -6.15,2.35 -6.15,2.35c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="143" + android:propertyName="pathData" + android:startOffset="88" + android:valueFrom="M-6.15 2.35 C-6.15,2.35 -6.15,2.35 -6.15,2.35 C-6.16,2.34 -6.15,2.35 -6.15,2.35 C-6.15,2.35 -6.14,2.36 -6.14,2.36 C-6.14,2.36 -4.7,0.94 -4.7,0.94 C-4.7,0.94 -4.72,0.93 -4.72,0.93 C-4.72,0.93 -4.7,0.94 -4.7,0.94 C-4.7,0.94 -6.15,2.35 -6.15,2.35c " + android:valueTo="M0.65 9.12 C0.65,9.12 0.66,9.13 0.66,9.13 C0.65,9.12 0.66,9.13 0.65,9.12 C0.65,9.12 -7.53,0.94 -7.53,0.94 C-7.53,0.94 -4.7,0.94 -4.7,0.94 C-4.7,0.94 1.78,7.42 1.78,7.42 C1.78,7.42 1.8,7.43 1.8,7.43 C1.8,7.43 0.65,9.12 0.65,9.12c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="17" + android:propertyName="pathData" + android:startOffset="232" + android:valueFrom="M0.65 9.12 C0.65,9.12 0.66,9.13 0.66,9.13 C0.65,9.12 0.66,9.13 0.65,9.12 C0.65,9.12 -7.53,0.94 -7.53,0.94 C-7.53,0.94 -4.7,0.94 -4.7,0.94 C-4.7,0.94 1.78,7.42 1.78,7.42 C1.78,7.42 1.8,7.43 1.8,7.43 C1.8,7.43 0.65,9.12 0.65,9.12c " + android:valueTo="M3.21 8.85 C3.21,8.85 2.94,9.08 2.94,9.08 C2.3,9.72 1.27,9.74 0.65,9.12 C0.65,9.12 -7.53,0.94 -7.53,0.94 C-7.53,0.94 -4.7,0.94 -4.7,0.94 C-4.7,0.94 1.78,7.42 1.78,7.42 C1.78,7.42 1.8,7.43 1.8,7.43 C1.8,7.43 3.21,8.85 3.21,8.85c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="418" + android:propertyName="pathData" + android:startOffset="248" + android:valueFrom="M3.21 8.85 C3.21,8.85 2.94,9.08 2.94,9.08 C2.3,9.72 1.27,9.74 0.65,9.12 C0.65,9.12 -7.53,0.94 -7.53,0.94 C-7.53,0.94 -4.7,0.94 -4.7,0.94 C-4.7,0.94 1.78,7.42 1.78,7.42 C1.78,7.42 1.8,7.43 1.8,7.43 C1.8,7.43 3.21,8.85 3.21,8.85c " + android:valueTo="M8.52 3.53 C8.52,3.53 2.94,9.08 2.94,9.08 C2.3,9.72 1.27,9.74 0.65,9.12 C0.65,9.12 -7.53,0.94 -7.53,0.94 C-7.53,0.94 -4.7,0.94 -4.7,0.94 C-4.7,0.94 1.78,7.42 1.78,7.42 C1.78,7.42 7.11,2.11 7.11,2.11 C7.11,2.11 8.52,3.53 8.52,3.53c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.1,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="250" + android:propertyName="rotation" + android:startOffset="0" + android:valueFrom="-135" + android:valueTo="-180" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="683" + android:propertyName="translateX" + android:startOffset="0" + android:valueFrom="0" + android:valueTo="1" + android:valueType="floatType" /> + </set> + </aapt:attr> + </target> + <aapt:attr name="android:drawable"> + <vector + android:width="24dp" + android:height="24dp" + android:viewportHeight="24" + android:viewportWidth="24"> + <group android:name="_R_G"> + <group + android:name="_R_G_L_2_G_N_1_T_0" + android:rotation="-135" + android:translateX="12.008" + android:translateY="11.992"> + <group + android:name="_R_G_L_2_G_T_1" + android:rotation="180" + android:translateX="7.062" + android:translateY="3.312"> + <group + android:name="_R_G_L_2_G" + android:translateX="6.984" + android:translateY="3.547"> + <path + android:name="_R_G_L_2_G_D_0_P_0" + android:fillAlpha="1" + android:fillColor="#ffffff" + android:fillType="nonZero" + android:pathData=" M-4.6 -1.06 C-4.6,-1.06 -9.55,-1.06 -9.55,-1.06 C-9.55,-1.06 -9.55,-6.01 -9.55,-6.01 C-9.55,-6.01 -7.55,-6 -7.55,-6 C-7.55,-6 -7.51,-3.04 -7.51,-3.04 C-7.51,-3.04 -4.6,-3.05 -4.6,-3.05 C-4.6,-3.05 -4.6,-1.06 -4.6,-1.06c " /> + </group> + </group> + </group> + <group + android:name="_R_G_L_1_G_N_1_T_0" + android:rotation="-135" + android:translateX="12.008" + android:translateY="11.992"> + <group + android:name="_R_G_L_1_G_T_1" + android:rotation="360" + android:translateX="-7" + android:translateY="-3.594"> + <group + android:name="_R_G_L_1_G" + android:translateX="6.984" + android:translateY="3.547"> + <path + android:name="_R_G_L_1_G_D_0_P_0" + android:fillAlpha="1" + android:fillColor="#ffffff" + android:fillType="nonZero" + android:pathData=" M-4.6 -1.06 C-4.6,-1.06 -9.55,-1.06 -9.55,-1.06 C-9.55,-1.06 -9.55,-6.01 -9.55,-6.01 C-9.55,-6.01 -7.55,-6 -7.55,-6 C-7.55,-6 -7.51,-3.04 -7.51,-3.04 C-7.51,-3.04 -4.6,-3.05 -4.6,-3.05 C-4.6,-3.05 -4.6,-1.06 -4.6,-1.06c " /> + </group> + </group> + </group> + <group + android:name="_R_G_L_0_G" + android:rotation="-135" + android:translateX="12.008" + android:translateY="11.992"> + <path + android:name="_R_G_L_0_G_D_0_P_0" + android:fillAlpha="1" + android:fillColor="#ffffff" + android:fillType="nonZero" + android:pathData=" M8.52 3.53 C8.52,3.53 2.94,9.08 2.94,9.08 C2.3,9.72 1.27,9.74 0.65,9.12 C0.65,9.12 -7.53,0.95 -7.53,0.95 C-7.53,0.95 -4.7,0.94 -4.7,0.94 C-4.7,0.94 1.78,7.42 1.78,7.42 C1.78,7.42 7.11,2.11 7.11,2.11 C7.11,2.11 7.14,2.14 7.14,2.14 C7.14,2.14 8.48,3.49 8.48,3.49 C8.48,3.49 8.5,3.51 8.5,3.51 C8.5,3.51 8.52,3.53 8.52,3.53c " /> + <path + android:name="_R_G_L_0_G_D_1_P_0" + android:fillAlpha="1" + android:fillColor="#ffffff" + android:fillType="nonZero" + android:pathData=" M-8.52 -3.53 C-8.52,-3.53 -2.94,-9.08 -2.94,-9.08 C-2.3,-9.72 -1.27,-9.74 -0.65,-9.12 C-0.65,-9.12 7.53,-0.95 7.53,-0.95 C7.53,-0.95 4.7,-0.94 4.7,-0.94 C4.7,-0.94 -1.78,-7.42 -1.78,-7.42 C-1.78,-7.42 -7.11,-2.11 -7.11,-2.11 C-7.11,-2.11 -7.14,-2.14 -7.14,-2.14 C-7.14,-2.14 -8.48,-3.49 -8.48,-3.49 C-8.48,-3.49 -8.5,-3.51 -8.5,-3.51 C-8.5,-3.51 -8.52,-3.53 -8.52,-3.53c " /> + <path + android:name="_R_G_L_0_G_D_2_P_0" + android:fillAlpha="1" + android:fillColor="#ffffff" + android:fillType="nonZero" + android:pathData=" M7.54 -0.94 C7.54,-0.94 7.54,-0.95 7.54,-0.95 C7.55,-0.94 7.54,-0.94 7.55,-0.94 C7.55,-0.94 7.53,-0.94 7.53,-0.94 C7.53,-0.94 7.52,-0.94 7.52,-0.94 C7.52,-0.94 7.54,-0.94 7.54,-0.94 C7.54,-0.94 7.52,-0.94 7.52,-0.94 C7.52,-0.94 7.54,-0.94 7.54,-0.94c " /> + <path + android:name="_R_G_L_0_G_D_3_P_0" + android:fillAlpha="1" + android:fillColor="#ffffff" + android:fillType="nonZero" + android:pathData=" M-7.54 0.94 C-7.54,0.94 -7.54,0.95 -7.54,0.95 C-7.55,0.94 -7.54,0.94 -7.54,0.94 C-7.54,0.94 -7.53,0.94 -7.53,0.94 C-7.53,0.94 -7.52,0.94 -7.52,0.94 C-7.52,0.94 -7.54,0.94 -7.54,0.94 C-7.54,0.94 -7.52,0.94 -7.52,0.94 C-7.52,0.94 -7.54,0.94 -7.54,0.94c " /> + </group> + </group> + <group android:name="time_group" /> + </vector> + </aapt:attr> +</animated-vector> diff --git a/packages/SystemUI/res-keyguard/drawable/qs_auto_rotate_icon_on.xml b/packages/SystemUI/res-keyguard/drawable/qs_auto_rotate_icon_on.xml new file mode 100644 index 000000000000..bd67d9f8dbaa --- /dev/null +++ b/packages/SystemUI/res-keyguard/drawable/qs_auto_rotate_icon_on.xml @@ -0,0 +1,781 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + ~ 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. + --> + +<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <target android:name="_R_G_L_2_G_D_0_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="367" + android:propertyName="fillAlpha" + android:startOffset="0" + android:valueFrom="1" + android:valueTo="1" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="17" + android:propertyName="fillAlpha" + android:startOffset="367" + android:valueFrom="1" + android:valueTo="0" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_2_G_D_0_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="17" + android:propertyName="pathData" + android:startOffset="0" + android:valueFrom="M8.52 3.53 C8.52,3.53 2.94,9.08 2.94,9.08 C2.3,9.72 1.27,9.74 0.65,9.12 C0.65,9.12 -7.53,0.95 -7.53,0.95 C-7.53,0.95 -4.7,0.94 -4.7,0.94 C-4.7,0.94 1.78,7.42 1.78,7.42 C1.78,7.42 7.11,2.11 7.11,2.11 C7.11,2.11 7.14,2.14 7.14,2.14 C7.14,2.14 8.48,3.49 8.48,3.49 C8.48,3.49 8.5,3.51 8.5,3.51 C8.5,3.51 8.52,3.53 8.52,3.53c " + android:valueTo="M8.82 3.18 C8.26,3.74 2.94,9.08 2.94,9.08 C2.3,9.72 1.27,9.74 0.65,9.12 C0.65,9.12 -6.08,2.36 -6.08,2.36 C-6.08,2.36 -4.7,0.94 -4.7,0.94 C-4.7,0.94 1.78,7.42 1.78,7.42 C1.78,7.42 7.5,1.77 7.5,1.77 C7.5,1.77 7.49,1.78 7.49,1.78 C7.49,1.78 8.87,0.41 8.87,0.41 C8.87,0.41 8.95,0.5 9.05,0.58 C9.86,1.4 9.7,2.29 8.82,3.18c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="41" + android:propertyName="pathData" + android:startOffset="17" + android:valueFrom="M8.82 3.18 C8.26,3.74 2.94,9.08 2.94,9.08 C2.3,9.72 1.27,9.74 0.65,9.12 C0.65,9.12 -6.08,2.36 -6.08,2.36 C-6.08,2.36 -4.7,0.94 -4.7,0.94 C-4.7,0.94 1.78,7.42 1.78,7.42 C1.78,7.42 7.5,1.77 7.5,1.77 C7.5,1.77 7.49,1.78 7.49,1.78 C7.49,1.78 8.87,0.41 8.87,0.41 C8.87,0.41 8.95,0.5 9.05,0.58 C9.86,1.4 9.7,2.29 8.82,3.18c " + android:valueTo="M8.82 3.18 C8.26,3.74 2.94,9.08 2.94,9.08 C2.3,9.72 1.27,9.74 0.65,9.12 C0.65,9.12 -2.78,5.89 -2.78,5.89 C-2.78,5.89 -1.29,4.47 -1.29,4.47 C-1.29,4.47 1.78,7.42 1.78,7.42 C1.78,7.42 7.5,1.77 7.5,1.77 C7.5,1.77 4.54,-1.11 4.54,-1.11 C4.54,-1.11 5.95,-2.51 5.95,-2.51 C5.95,-2.51 8.36,-0.12 9.05,0.58 C9.86,1.4 9.7,2.29 8.82,3.18c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="45" + android:propertyName="pathData" + android:startOffset="59" + android:valueFrom="M8.82 3.18 C8.26,3.74 2.94,9.08 2.94,9.08 C2.3,9.72 1.27,9.74 0.65,9.12 C0.65,9.12 -2.78,5.89 -2.78,5.89 C-2.78,5.89 -1.29,4.47 -1.29,4.47 C-1.29,4.47 1.78,7.42 1.78,7.42 C1.78,7.42 7.5,1.77 7.5,1.77 C7.5,1.77 4.54,-1.11 4.54,-1.11 C4.54,-1.11 5.95,-2.51 5.95,-2.51 C5.95,-2.51 8.36,-0.12 9.05,0.58 C9.86,1.4 9.7,2.29 8.82,3.18c " + android:valueTo="M8.82 3.18 C8.26,3.74 2.94,9.08 2.94,9.08 C2.3,9.72 1.27,9.74 0.65,9.12 C0.65,9.12 0.36,8.83 0.36,8.83 C0.36,8.83 1.8,7.44 1.8,7.44 C1.8,7.44 1.78,7.42 1.78,7.42 C1.78,7.42 7.5,1.77 7.5,1.77 C7.5,1.77 4.54,-1.11 4.54,-1.11 C4.54,-1.11 5.95,-2.51 5.95,-2.51 C5.95,-2.51 8.36,-0.12 9.05,0.58 C9.86,1.4 9.7,2.29 8.82,3.18c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="17" + android:propertyName="pathData" + android:startOffset="103" + android:valueFrom="M8.82 3.18 C8.26,3.74 2.94,9.08 2.94,9.08 C2.3,9.72 1.27,9.74 0.65,9.12 C0.65,9.12 0.36,8.83 0.36,8.83 C0.36,8.83 1.8,7.44 1.8,7.44 C1.8,7.44 1.78,7.42 1.78,7.42 C1.78,7.42 7.5,1.77 7.5,1.77 C7.5,1.77 4.54,-1.11 4.54,-1.11 C4.54,-1.11 5.95,-2.51 5.95,-2.51 C5.95,-2.51 8.36,-0.12 9.05,0.58 C9.86,1.4 9.7,2.29 8.82,3.18c " + android:valueTo="M8.82 3.18 C8.26,3.74 3.22,8.8 3.22,8.8 C3.22,8.8 3.21,8.79 3.21,8.79 C3.21,8.79 3.24,8.8 3.24,8.8 C3.24,8.8 1.8,7.44 1.8,7.44 C1.8,7.44 1.78,7.42 1.78,7.42 C1.78,7.42 7.5,1.77 7.5,1.77 C7.5,1.77 4.54,-1.11 4.54,-1.11 C4.54,-1.11 5.95,-2.51 5.95,-2.51 C5.95,-2.51 8.36,-0.12 9.05,0.58 C9.86,1.4 9.7,2.29 8.82,3.18c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="34" + android:propertyName="pathData" + android:startOffset="121" + android:valueFrom="M8.82 3.18 C8.26,3.74 3.22,8.8 3.22,8.8 C3.22,8.8 3.21,8.79 3.21,8.79 C3.21,8.79 3.24,8.8 3.24,8.8 C3.24,8.8 1.8,7.44 1.8,7.44 C1.8,7.44 1.78,7.42 1.78,7.42 C1.78,7.42 7.5,1.77 7.5,1.77 C7.5,1.77 4.54,-1.11 4.54,-1.11 C4.54,-1.11 5.95,-2.51 5.95,-2.51 C5.95,-2.51 8.36,-0.12 9.05,0.58 C9.86,1.4 9.7,2.29 8.82,3.18c " + android:valueTo="M8.82 3.18 C8.26,3.74 5.82,6.14 5.82,6.14 C5.82,6.14 5.81,6.14 5.81,6.14 C5.81,6.14 5.83,6.14 5.83,6.14 C5.83,6.14 4.39,4.78 4.39,4.78 C4.39,4.78 4.37,4.76 4.37,4.76 C4.37,4.76 7.5,1.77 7.5,1.77 C7.5,1.77 4.54,-1.11 4.54,-1.11 C4.54,-1.11 5.95,-2.51 5.95,-2.51 C5.95,-2.51 8.36,-0.12 9.05,0.58 C9.86,1.4 9.7,2.29 8.82,3.18c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="26" + android:propertyName="pathData" + android:startOffset="155" + android:valueFrom="M8.82 3.18 C8.26,3.74 5.82,6.14 5.82,6.14 C5.82,6.14 5.81,6.14 5.81,6.14 C5.81,6.14 5.83,6.14 5.83,6.14 C5.83,6.14 4.39,4.78 4.39,4.78 C4.39,4.78 4.37,4.76 4.37,4.76 C4.37,4.76 7.5,1.77 7.5,1.77 C7.5,1.77 4.54,-1.11 4.54,-1.11 C4.54,-1.11 5.95,-2.51 5.95,-2.51 C5.95,-2.51 8.36,-0.12 9.05,0.58 C9.86,1.4 9.7,2.29 8.82,3.18c " + android:valueTo="M8.91 3.09 C8.91,3.09 8.91,3.1 8.91,3.1 C8.91,3.1 8.9,3.09 8.9,3.09 C8.9,3.09 7.49,1.74 7.49,1.74 C7.49,1.74 7.5,1.75 7.5,1.75 C7.5,1.75 7.48,1.73 7.48,1.73 C7.48,1.73 7.5,1.77 7.5,1.77 C7.5,1.77 4.54,-1.11 4.54,-1.11 C4.54,-1.11 5.95,-2.51 5.95,-2.51 C5.95,-2.51 8.36,-0.12 9.05,0.58 C9.86,1.4 9.79,2.2 8.91,3.09c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="17" + android:propertyName="pathData" + android:startOffset="181" + android:valueFrom="M8.91 3.09 C8.91,3.09 8.91,3.1 8.91,3.1 C8.91,3.1 8.9,3.09 8.9,3.09 C8.9,3.09 7.49,1.74 7.49,1.74 C7.49,1.74 7.5,1.75 7.5,1.75 C7.5,1.75 7.48,1.73 7.48,1.73 C7.48,1.73 7.5,1.77 7.5,1.77 C7.5,1.77 4.54,-1.11 4.54,-1.11 C4.54,-1.11 5.95,-2.51 5.95,-2.51 C5.95,-2.51 8.36,-0.12 9.05,0.58 C9.86,1.4 9.79,2.2 8.91,3.09c " + android:valueTo="M9.05 0.57 C9.05,0.57 9.05,0.58 9.05,0.58 C9.05,0.58 9.04,0.57 9.04,0.57 C9.04,0.57 7.6,1.83 7.6,1.83 C7.6,1.83 7.61,1.85 7.61,1.85 C7.61,1.85 7.59,1.83 7.59,1.83 C7.59,1.83 7.61,1.86 7.61,1.86 C7.61,1.86 4.54,-1.11 4.54,-1.11 C4.54,-1.11 5.95,-2.51 5.95,-2.51 C5.95,-2.51 9.05,0.58 9.05,0.58 C9.05,0.58 9.05,0.57 9.05,0.57c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="52" + android:propertyName="pathData" + android:startOffset="198" + android:valueFrom="M9.05 0.57 C9.05,0.57 9.05,0.58 9.05,0.58 C9.05,0.58 9.04,0.57 9.04,0.57 C9.04,0.57 7.6,1.83 7.6,1.83 C7.6,1.83 7.61,1.85 7.61,1.85 C7.61,1.85 7.59,1.83 7.59,1.83 C7.59,1.83 7.61,1.86 7.61,1.86 C7.61,1.86 4.54,-1.11 4.54,-1.11 C4.54,-1.11 5.95,-2.51 5.95,-2.51 C5.95,-2.51 9.05,0.58 9.05,0.58 C9.05,0.58 9.05,0.57 9.05,0.57c " + android:valueTo="M5.94 -2.52 C5.94,-2.52 5.94,-2.51 5.94,-2.51 C5.94,-2.51 5.93,-2.52 5.93,-2.52 C5.93,-2.52 4.53,-1.12 4.53,-1.12 C4.53,-1.12 4.55,-1.11 4.55,-1.11 C4.55,-1.11 4.53,-1.13 4.53,-1.13 C4.53,-1.13 4.55,-1.09 4.55,-1.09 C4.55,-1.09 4.54,-1.11 4.54,-1.11 C4.54,-1.11 5.95,-2.51 5.95,-2.51 C5.95,-2.51 5.94,-2.52 5.94,-2.52 C5.94,-2.52 5.94,-2.52 5.94,-2.52c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.1,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_2_G_D_1_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="367" + android:propertyName="fillAlpha" + android:startOffset="0" + android:valueFrom="1" + android:valueTo="1" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="17" + android:propertyName="fillAlpha" + android:startOffset="367" + android:valueFrom="1" + android:valueTo="0" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_2_G_D_1_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="17" + android:propertyName="pathData" + android:startOffset="0" + android:valueFrom="M-8.52 -3.53 C-8.52,-3.53 -2.94,-9.08 -2.94,-9.08 C-2.3,-9.72 -1.27,-9.74 -0.65,-9.12 C-0.65,-9.12 7.53,-0.95 7.53,-0.95 C7.53,-0.95 4.7,-0.94 4.7,-0.94 C4.7,-0.94 -1.78,-7.42 -1.78,-7.42 C-1.78,-7.42 -7.11,-2.11 -7.11,-2.11 C-7.11,-2.11 -7.14,-2.14 -7.14,-2.14 C-7.14,-2.14 -8.48,-3.49 -8.48,-3.49 C-8.48,-3.49 -8.5,-3.51 -8.5,-3.51 C-8.5,-3.51 -8.52,-3.53 -8.52,-3.53c " + android:valueTo="M-8.82 -3.18 C-8.26,-3.74 -2.94,-9.08 -2.94,-9.08 C-2.3,-9.72 -1.27,-9.74 -0.65,-9.12 C-0.65,-9.12 6.08,-2.36 6.08,-2.36 C6.08,-2.36 4.7,-0.94 4.7,-0.94 C4.7,-0.94 -1.78,-7.42 -1.78,-7.42 C-1.78,-7.42 -7.5,-1.77 -7.5,-1.77 C-7.5,-1.77 -7.49,-1.78 -7.49,-1.78 C-7.49,-1.78 -8.87,-0.41 -8.87,-0.41 C-8.87,-0.41 -8.95,-0.5 -9.05,-0.58 C-9.86,-1.4 -9.7,-2.29 -8.82,-3.18c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="41" + android:propertyName="pathData" + android:startOffset="17" + android:valueFrom="M-8.82 -3.18 C-8.26,-3.74 -2.94,-9.08 -2.94,-9.08 C-2.3,-9.72 -1.27,-9.74 -0.65,-9.12 C-0.65,-9.12 6.08,-2.36 6.08,-2.36 C6.08,-2.36 4.7,-0.94 4.7,-0.94 C4.7,-0.94 -1.78,-7.42 -1.78,-7.42 C-1.78,-7.42 -7.5,-1.77 -7.5,-1.77 C-7.5,-1.77 -7.49,-1.78 -7.49,-1.78 C-7.49,-1.78 -8.87,-0.41 -8.87,-0.41 C-8.87,-0.41 -8.95,-0.5 -9.05,-0.58 C-9.86,-1.4 -9.7,-2.29 -8.82,-3.18c " + android:valueTo="M-8.82 -3.18 C-8.26,-3.74 -2.94,-9.08 -2.94,-9.08 C-2.3,-9.72 -1.27,-9.74 -0.65,-9.12 C-0.65,-9.12 2.78,-5.89 2.78,-5.89 C2.78,-5.89 1.29,-4.47 1.29,-4.47 C1.29,-4.47 -1.78,-7.42 -1.78,-7.42 C-1.78,-7.42 -7.5,-1.77 -7.5,-1.77 C-7.5,-1.77 -4.54,1.11 -4.54,1.11 C-4.54,1.11 -5.95,2.51 -5.95,2.51 C-5.95,2.51 -8.36,0.12 -9.05,-0.58 C-9.86,-1.4 -9.7,-2.29 -8.82,-3.18c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="45" + android:propertyName="pathData" + android:startOffset="59" + android:valueFrom="M-8.82 -3.18 C-8.26,-3.74 -2.94,-9.08 -2.94,-9.08 C-2.3,-9.72 -1.27,-9.74 -0.65,-9.12 C-0.65,-9.12 2.78,-5.89 2.78,-5.89 C2.78,-5.89 1.29,-4.47 1.29,-4.47 C1.29,-4.47 -1.78,-7.42 -1.78,-7.42 C-1.78,-7.42 -7.5,-1.77 -7.5,-1.77 C-7.5,-1.77 -4.54,1.11 -4.54,1.11 C-4.54,1.11 -5.95,2.51 -5.95,2.51 C-5.95,2.51 -8.36,0.12 -9.05,-0.58 C-9.86,-1.4 -9.7,-2.29 -8.82,-3.18c " + android:valueTo="M-8.82 -3.18 C-8.26,-3.74 -2.94,-9.08 -2.94,-9.08 C-2.3,-9.72 -1.27,-9.74 -0.65,-9.12 C-0.65,-9.12 -0.36,-8.83 -0.36,-8.83 C-0.36,-8.83 -1.8,-7.44 -1.8,-7.44 C-1.8,-7.44 -1.78,-7.42 -1.78,-7.42 C-1.78,-7.42 -7.5,-1.77 -7.5,-1.77 C-7.5,-1.77 -4.54,1.11 -4.54,1.11 C-4.54,1.11 -5.95,2.51 -5.95,2.51 C-5.95,2.51 -8.36,0.12 -9.05,-0.58 C-9.86,-1.4 -9.7,-2.29 -8.82,-3.18c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="17" + android:propertyName="pathData" + android:startOffset="103" + android:valueFrom="M-8.82 -3.18 C-8.26,-3.74 -2.94,-9.08 -2.94,-9.08 C-2.3,-9.72 -1.27,-9.74 -0.65,-9.12 C-0.65,-9.12 -0.36,-8.83 -0.36,-8.83 C-0.36,-8.83 -1.8,-7.44 -1.8,-7.44 C-1.8,-7.44 -1.78,-7.42 -1.78,-7.42 C-1.78,-7.42 -7.5,-1.77 -7.5,-1.77 C-7.5,-1.77 -4.54,1.11 -4.54,1.11 C-4.54,1.11 -5.95,2.51 -5.95,2.51 C-5.95,2.51 -8.36,0.12 -9.05,-0.58 C-9.86,-1.4 -9.7,-2.29 -8.82,-3.18c " + android:valueTo="M-8.82 -3.18 C-8.26,-3.74 -3.22,-8.8 -3.22,-8.8 C-3.22,-8.8 -3.21,-8.79 -3.21,-8.79 C-3.21,-8.79 -3.24,-8.8 -3.24,-8.8 C-3.24,-8.8 -1.8,-7.44 -1.8,-7.44 C-1.8,-7.44 -1.78,-7.42 -1.78,-7.42 C-1.78,-7.42 -7.5,-1.77 -7.5,-1.77 C-7.5,-1.77 -4.54,1.11 -4.54,1.11 C-4.54,1.11 -5.95,2.51 -5.95,2.51 C-5.95,2.51 -8.36,0.12 -9.05,-0.58 C-9.86,-1.4 -9.7,-2.29 -8.82,-3.18c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="34" + android:propertyName="pathData" + android:startOffset="121" + android:valueFrom="M-8.82 -3.18 C-8.26,-3.74 -3.22,-8.8 -3.22,-8.8 C-3.22,-8.8 -3.21,-8.79 -3.21,-8.79 C-3.21,-8.79 -3.24,-8.8 -3.24,-8.8 C-3.24,-8.8 -1.8,-7.44 -1.8,-7.44 C-1.8,-7.44 -1.78,-7.42 -1.78,-7.42 C-1.78,-7.42 -7.5,-1.77 -7.5,-1.77 C-7.5,-1.77 -4.54,1.11 -4.54,1.11 C-4.54,1.11 -5.95,2.51 -5.95,2.51 C-5.95,2.51 -8.36,0.12 -9.05,-0.58 C-9.86,-1.4 -9.7,-2.29 -8.82,-3.18c " + android:valueTo="M-8.82 -3.18 C-8.26,-3.74 -5.81,-6.14 -5.81,-6.14 C-5.81,-6.14 -5.81,-6.13 -5.81,-6.13 C-5.81,-6.13 -5.83,-6.14 -5.83,-6.14 C-5.83,-6.14 -4.39,-4.78 -4.39,-4.78 C-4.39,-4.78 -4.37,-4.76 -4.37,-4.76 C-4.37,-4.76 -7.5,-1.77 -7.5,-1.77 C-7.5,-1.77 -4.54,1.11 -4.54,1.11 C-4.54,1.11 -5.95,2.51 -5.95,2.51 C-5.95,2.51 -8.36,0.12 -9.05,-0.58 C-9.86,-1.4 -9.7,-2.29 -8.82,-3.18c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="26" + android:propertyName="pathData" + android:startOffset="155" + android:valueFrom="M-8.82 -3.18 C-8.26,-3.74 -5.81,-6.14 -5.81,-6.14 C-5.81,-6.14 -5.81,-6.13 -5.81,-6.13 C-5.81,-6.13 -5.83,-6.14 -5.83,-6.14 C-5.83,-6.14 -4.39,-4.78 -4.39,-4.78 C-4.39,-4.78 -4.37,-4.76 -4.37,-4.76 C-4.37,-4.76 -7.5,-1.77 -7.5,-1.77 C-7.5,-1.77 -4.54,1.11 -4.54,1.11 C-4.54,1.11 -5.95,2.51 -5.95,2.51 C-5.95,2.51 -8.36,0.12 -9.05,-0.58 C-9.86,-1.4 -9.7,-2.29 -8.82,-3.18c " + android:valueTo="M-8.91 -3.09 C-8.91,-3.09 -8.91,-3.09 -8.91,-3.09 C-8.91,-3.09 -8.9,-3.09 -8.9,-3.09 C-8.9,-3.09 -7.49,-1.74 -7.49,-1.74 C-7.49,-1.74 -7.5,-1.75 -7.5,-1.75 C-7.5,-1.75 -7.48,-1.73 -7.48,-1.73 C-7.48,-1.73 -7.5,-1.77 -7.5,-1.77 C-7.5,-1.77 -4.54,1.11 -4.54,1.11 C-4.54,1.11 -5.95,2.51 -5.95,2.51 C-5.95,2.51 -8.36,0.12 -9.05,-0.58 C-9.86,-1.4 -9.79,-2.2 -8.91,-3.09c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="17" + android:propertyName="pathData" + android:startOffset="181" + android:valueFrom="M-8.91 -3.09 C-8.91,-3.09 -8.91,-3.09 -8.91,-3.09 C-8.91,-3.09 -8.9,-3.09 -8.9,-3.09 C-8.9,-3.09 -7.49,-1.74 -7.49,-1.74 C-7.49,-1.74 -7.5,-1.75 -7.5,-1.75 C-7.5,-1.75 -7.48,-1.73 -7.48,-1.73 C-7.48,-1.73 -7.5,-1.77 -7.5,-1.77 C-7.5,-1.77 -4.54,1.11 -4.54,1.11 C-4.54,1.11 -5.95,2.51 -5.95,2.51 C-5.95,2.51 -8.36,0.12 -9.05,-0.58 C-9.86,-1.4 -9.79,-2.2 -8.91,-3.09c " + android:valueTo="M-9.05 -0.57 C-9.05,-0.57 -9.05,-0.58 -9.05,-0.58 C-9.05,-0.58 -9.04,-0.57 -9.04,-0.57 C-9.04,-0.57 -7.59,-1.83 -7.59,-1.83 C-7.59,-1.83 -7.61,-1.85 -7.61,-1.85 C-7.61,-1.85 -7.59,-1.83 -7.59,-1.83 C-7.59,-1.83 -7.61,-1.86 -7.61,-1.86 C-7.61,-1.86 -4.54,1.11 -4.54,1.11 C-4.54,1.11 -5.95,2.51 -5.95,2.51 C-5.95,2.51 -9.05,-0.58 -9.05,-0.58 C-9.05,-0.58 -9.05,-0.57 -9.05,-0.57c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="52" + android:propertyName="pathData" + android:startOffset="198" + android:valueFrom="M-9.05 -0.57 C-9.05,-0.57 -9.05,-0.58 -9.05,-0.58 C-9.05,-0.58 -9.04,-0.57 -9.04,-0.57 C-9.04,-0.57 -7.59,-1.83 -7.59,-1.83 C-7.59,-1.83 -7.61,-1.85 -7.61,-1.85 C-7.61,-1.85 -7.59,-1.83 -7.59,-1.83 C-7.59,-1.83 -7.61,-1.86 -7.61,-1.86 C-7.61,-1.86 -4.54,1.11 -4.54,1.11 C-4.54,1.11 -5.95,2.51 -5.95,2.51 C-5.95,2.51 -9.05,-0.58 -9.05,-0.58 C-9.05,-0.58 -9.05,-0.57 -9.05,-0.57c " + android:valueTo="M-5.94 2.52 C-5.94,2.52 -5.94,2.51 -5.94,2.51 C-5.94,2.51 -5.93,2.52 -5.93,2.52 C-5.93,2.52 -4.53,1.12 -4.53,1.12 C-4.53,1.12 -4.55,1.11 -4.55,1.11 C-4.55,1.11 -4.53,1.13 -4.53,1.13 C-4.53,1.13 -4.55,1.09 -4.55,1.09 C-4.55,1.09 -4.54,1.11 -4.54,1.11 C-4.54,1.11 -5.95,2.51 -5.95,2.51 C-5.95,2.51 -5.94,2.52 -5.94,2.52 C-5.94,2.52 -5.94,2.52 -5.94,2.52c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.1,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_2_G_D_2_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="38" + android:propertyName="pathData" + android:startOffset="0" + android:valueFrom="M7.54 -0.94 C7.54,-0.94 7.54,-0.95 7.54,-0.95 C7.55,-0.94 7.54,-0.94 7.55,-0.94 C7.55,-0.94 7.53,-0.94 7.53,-0.94 C7.53,-0.94 7.52,-0.94 7.52,-0.94 C7.52,-0.94 7.54,-0.94 7.54,-0.94 C7.54,-0.94 7.52,-0.94 7.52,-0.94 C7.52,-0.94 7.54,-0.94 7.54,-0.94c " + android:valueTo="M7.54 -0.94 C7.54,-0.94 7.54,-0.95 7.54,-0.95 C7.55,-0.94 7.54,-0.94 7.55,-0.94 C7.55,-0.94 7.53,-0.94 7.53,-0.94 C7.53,-0.94 7.52,-0.94 7.52,-0.94 C7.52,-0.94 7.54,-0.94 7.54,-0.94 C7.54,-0.94 7.52,-0.94 7.52,-0.94 C7.52,-0.94 7.54,-0.94 7.54,-0.94c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="17" + android:propertyName="pathData" + android:startOffset="38" + android:valueFrom="M7.54 -0.94 C7.54,-0.94 7.54,-0.95 7.54,-0.95 C7.55,-0.94 7.54,-0.94 7.55,-0.94 C7.55,-0.94 7.53,-0.94 7.53,-0.94 C7.53,-0.94 7.52,-0.94 7.52,-0.94 C7.52,-0.94 7.54,-0.94 7.54,-0.94 C7.54,-0.94 7.52,-0.94 7.52,-0.94 C7.52,-0.94 7.54,-0.94 7.54,-0.94c " + android:valueTo="M6.15 -2.35 C6.15,-2.35 6.15,-2.35 6.15,-2.35 C6.16,-2.34 6.15,-2.35 6.16,-2.35 C6.16,-2.35 7.53,-0.94 7.53,-0.94 C7.53,-0.94 4.7,-0.94 4.7,-0.94 C4.7,-0.94 4.72,-0.93 4.72,-0.93 C4.72,-0.93 4.7,-0.94 4.7,-0.94 C4.7,-0.94 6.15,-2.35 6.15,-2.35c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="90" + android:propertyName="pathData" + android:startOffset="55" + android:valueFrom="M6.15 -2.35 C6.15,-2.35 6.15,-2.35 6.15,-2.35 C6.16,-2.34 6.15,-2.35 6.16,-2.35 C6.16,-2.35 7.53,-0.94 7.53,-0.94 C7.53,-0.94 4.7,-0.94 4.7,-0.94 C4.7,-0.94 4.72,-0.93 4.72,-0.93 C4.72,-0.93 4.7,-0.94 4.7,-0.94 C4.7,-0.94 6.15,-2.35 6.15,-2.35c " + android:valueTo="M-0.65 -9.12 C-0.65,-9.12 -0.66,-9.13 -0.66,-9.13 C-0.65,-9.12 -0.66,-9.12 -0.65,-9.12 C-0.65,-9.12 7.53,-0.94 7.53,-0.94 C7.53,-0.94 4.7,-0.94 4.7,-0.94 C4.7,-0.94 -1.78,-7.42 -1.78,-7.42 C-1.78,-7.42 -1.8,-7.43 -1.8,-7.43 C-1.8,-7.43 -0.65,-9.12 -0.65,-9.12c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="10" + android:propertyName="pathData" + android:startOffset="145" + android:valueFrom="M-0.65 -9.12 C-0.65,-9.12 -0.66,-9.13 -0.66,-9.13 C-0.65,-9.12 -0.66,-9.12 -0.65,-9.12 C-0.65,-9.12 7.53,-0.94 7.53,-0.94 C7.53,-0.94 4.7,-0.94 4.7,-0.94 C4.7,-0.94 -1.78,-7.42 -1.78,-7.42 C-1.78,-7.42 -1.8,-7.43 -1.8,-7.43 C-1.8,-7.43 -0.65,-9.12 -0.65,-9.12c " + android:valueTo="M-3.21 -8.85 C-3.21,-8.85 -2.94,-9.08 -2.94,-9.08 C-2.3,-9.72 -1.27,-9.74 -0.65,-9.12 C-0.65,-9.12 7.53,-0.94 7.53,-0.94 C7.53,-0.94 4.7,-0.94 4.7,-0.94 C4.7,-0.94 -1.78,-7.42 -1.78,-7.42 C-1.78,-7.42 -1.8,-7.43 -1.8,-7.43 C-1.8,-7.43 -3.21,-8.85 -3.21,-8.85c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="261" + android:propertyName="pathData" + android:startOffset="155" + android:valueFrom="M-3.21 -8.85 C-3.21,-8.85 -2.94,-9.08 -2.94,-9.08 C-2.3,-9.72 -1.27,-9.74 -0.65,-9.12 C-0.65,-9.12 7.53,-0.94 7.53,-0.94 C7.53,-0.94 4.7,-0.94 4.7,-0.94 C4.7,-0.94 -1.78,-7.42 -1.78,-7.42 C-1.78,-7.42 -1.8,-7.43 -1.8,-7.43 C-1.8,-7.43 -3.21,-8.85 -3.21,-8.85c " + android:valueTo="M-8.52 -3.53 C-8.52,-3.53 -2.94,-9.08 -2.94,-9.08 C-2.3,-9.72 -1.27,-9.74 -0.65,-9.12 C-0.65,-9.12 7.53,-0.94 7.53,-0.94 C7.53,-0.94 4.7,-0.94 4.7,-0.94 C4.7,-0.94 -1.78,-7.42 -1.78,-7.42 C-1.78,-7.42 -7.11,-2.11 -7.11,-2.11 C-7.11,-2.11 -8.52,-3.53 -8.52,-3.53c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.1,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_2_G_D_3_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="38" + android:propertyName="pathData" + android:startOffset="0" + android:valueFrom="M-7.54 0.94 C-7.54,0.94 -7.54,0.95 -7.54,0.95 C-7.55,0.94 -7.54,0.94 -7.54,0.94 C-7.54,0.94 -7.53,0.94 -7.53,0.94 C-7.53,0.94 -7.52,0.94 -7.52,0.94 C-7.52,0.94 -7.54,0.94 -7.54,0.94 C-7.54,0.94 -7.52,0.94 -7.52,0.94 C-7.52,0.94 -7.54,0.94 -7.54,0.94c " + android:valueTo="M-7.54 0.94 C-7.54,0.94 -7.54,0.95 -7.54,0.95 C-7.55,0.94 -7.54,0.94 -7.54,0.94 C-7.54,0.94 -7.53,0.94 -7.53,0.94 C-7.53,0.94 -7.52,0.94 -7.52,0.94 C-7.52,0.94 -7.54,0.94 -7.54,0.94 C-7.54,0.94 -7.52,0.94 -7.52,0.94 C-7.52,0.94 -7.54,0.94 -7.54,0.94c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="17" + android:propertyName="pathData" + android:startOffset="38" + android:valueFrom="M-7.54 0.94 C-7.54,0.94 -7.54,0.95 -7.54,0.95 C-7.55,0.94 -7.54,0.94 -7.54,0.94 C-7.54,0.94 -7.53,0.94 -7.53,0.94 C-7.53,0.94 -7.52,0.94 -7.52,0.94 C-7.52,0.94 -7.54,0.94 -7.54,0.94 C-7.54,0.94 -7.52,0.94 -7.52,0.94 C-7.52,0.94 -7.54,0.94 -7.54,0.94c " + android:valueTo="M-6.15 2.35 C-6.15,2.35 -6.15,2.35 -6.15,2.35 C-6.16,2.34 -6.15,2.35 -6.15,2.35 C-6.15,2.35 -6.14,2.36 -6.14,2.36 C-6.14,2.36 -4.7,0.94 -4.7,0.94 C-4.7,0.94 -4.72,0.93 -4.72,0.93 C-4.72,0.93 -4.7,0.94 -4.7,0.94 C-4.7,0.94 -6.15,2.35 -6.15,2.35c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="90" + android:propertyName="pathData" + android:startOffset="55" + android:valueFrom="M-6.15 2.35 C-6.15,2.35 -6.15,2.35 -6.15,2.35 C-6.16,2.34 -6.15,2.35 -6.15,2.35 C-6.15,2.35 -6.14,2.36 -6.14,2.36 C-6.14,2.36 -4.7,0.94 -4.7,0.94 C-4.7,0.94 -4.72,0.93 -4.72,0.93 C-4.72,0.93 -4.7,0.94 -4.7,0.94 C-4.7,0.94 -6.15,2.35 -6.15,2.35c " + android:valueTo="M0.65 9.12 C0.65,9.12 0.66,9.13 0.66,9.13 C0.65,9.12 0.66,9.13 0.65,9.12 C0.65,9.12 -7.53,0.94 -7.53,0.94 C-7.53,0.94 -4.7,0.94 -4.7,0.94 C-4.7,0.94 1.78,7.42 1.78,7.42 C1.78,7.42 1.8,7.43 1.8,7.43 C1.8,7.43 0.65,9.12 0.65,9.12c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="10" + android:propertyName="pathData" + android:startOffset="145" + android:valueFrom="M0.65 9.12 C0.65,9.12 0.66,9.13 0.66,9.13 C0.65,9.12 0.66,9.13 0.65,9.12 C0.65,9.12 -7.53,0.94 -7.53,0.94 C-7.53,0.94 -4.7,0.94 -4.7,0.94 C-4.7,0.94 1.78,7.42 1.78,7.42 C1.78,7.42 1.8,7.43 1.8,7.43 C1.8,7.43 0.65,9.12 0.65,9.12c " + android:valueTo="M3.21 8.85 C3.21,8.85 2.94,9.08 2.94,9.08 C2.3,9.72 1.27,9.74 0.65,9.12 C0.65,9.12 -7.53,0.94 -7.53,0.94 C-7.53,0.94 -4.7,0.94 -4.7,0.94 C-4.7,0.94 1.78,7.42 1.78,7.42 C1.78,7.42 1.8,7.43 1.8,7.43 C1.8,7.43 3.21,8.85 3.21,8.85c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="261" + android:propertyName="pathData" + android:startOffset="155" + android:valueFrom="M3.21 8.85 C3.21,8.85 2.94,9.08 2.94,9.08 C2.3,9.72 1.27,9.74 0.65,9.12 C0.65,9.12 -7.53,0.94 -7.53,0.94 C-7.53,0.94 -4.7,0.94 -4.7,0.94 C-4.7,0.94 1.78,7.42 1.78,7.42 C1.78,7.42 1.8,7.43 1.8,7.43 C1.8,7.43 3.21,8.85 3.21,8.85c " + android:valueTo="M8.52 3.53 C8.52,3.53 2.94,9.08 2.94,9.08 C2.3,9.72 1.27,9.74 0.65,9.12 C0.65,9.12 -7.53,0.94 -7.53,0.94 C-7.53,0.94 -4.7,0.94 -4.7,0.94 C-4.7,0.94 1.78,7.42 1.78,7.42 C1.78,7.42 7.11,2.11 7.11,2.11 C7.11,2.11 8.52,3.53 8.52,3.53c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.1,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_2_G"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="367" + android:propertyName="rotation" + android:startOffset="0" + android:valueFrom="0" + android:valueTo="-135" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_1_G_T_1"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="17" + android:propertyName="translateX" + android:startOffset="0" + android:valueFrom="-7" + android:valueTo="-8.859" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="138" + android:propertyName="translateX" + android:startOffset="17" + android:valueFrom="-8.859" + android:valueTo="1.734" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="261" + android:propertyName="translateX" + android:startOffset="155" + android:valueFrom="1.734" + android:valueTo="7" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.1,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_1_G_T_1"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="17" + android:propertyName="translateY" + android:startOffset="0" + android:valueFrom="-3.594" + android:valueTo="-1.922" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="138" + android:propertyName="translateY" + android:startOffset="17" + android:valueFrom="-1.922" + android:valueTo="8.671" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="261" + android:propertyName="translateY" + android:startOffset="155" + android:valueFrom="8.671" + android:valueTo="3.5" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.1,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_1_G_T_1"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="17" + android:propertyName="rotation" + android:startOffset="0" + android:valueFrom="360" + android:valueTo="270" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="103" + android:propertyName="rotation" + android:startOffset="17" + android:valueFrom="270" + android:valueTo="270" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="34" + android:propertyName="rotation" + android:startOffset="121" + android:valueFrom="270" + android:valueTo="180" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="261" + android:propertyName="rotation" + android:startOffset="155" + android:valueFrom="180" + android:valueTo="180" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0 0.1,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_1_G_N_3_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="367" + android:propertyName="rotation" + android:startOffset="0" + android:valueFrom="0" + android:valueTo="-135" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G_T_1"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="17" + android:propertyName="translateX" + android:startOffset="0" + android:valueFrom="7.062" + android:valueTo="8.578" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="138" + android:propertyName="translateX" + android:startOffset="17" + android:valueFrom="8.578" + android:valueTo="-1.656" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="261" + android:propertyName="translateX" + android:startOffset="155" + android:valueFrom="-1.656" + android:valueTo="-7" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.1,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G_T_1"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="17" + android:propertyName="translateY" + android:startOffset="0" + android:valueFrom="3.312" + android:valueTo="2.016" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="138" + android:propertyName="translateY" + android:startOffset="17" + android:valueFrom="2.016" + android:valueTo="-8.656" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="261" + android:propertyName="translateY" + android:startOffset="155" + android:valueFrom="-8.656" + android:valueTo="-3.5" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.1,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G_T_1"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="17" + android:propertyName="rotation" + android:startOffset="0" + android:valueFrom="180" + android:valueTo="90" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="103" + android:propertyName="rotation" + android:startOffset="17" + android:valueFrom="90" + android:valueTo="90" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="34" + android:propertyName="rotation" + android:startOffset="121" + android:valueFrom="90" + android:valueTo="0" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G_N_3_T_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="367" + android:propertyName="rotation" + android:startOffset="0" + android:valueFrom="0" + android:valueTo="-135" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="433" + android:propertyName="translateX" + android:startOffset="0" + android:valueFrom="0" + android:valueTo="1" + android:valueType="floatType" /> + </set> + </aapt:attr> + </target> + <aapt:attr name="android:drawable"> + <vector + android:width="24dp" + android:height="24dp" + android:viewportHeight="24" + android:viewportWidth="24"> + <group android:name="_R_G"> + <group + android:name="_R_G_L_2_G" + android:rotation="0" + android:translateX="12" + android:translateY="12"> + <path + android:name="_R_G_L_2_G_D_0_P_0" + android:fillAlpha="1" + android:fillColor="#ffffff" + android:fillType="nonZero" + android:pathData=" M8.52 3.53 C8.52,3.53 2.94,9.08 2.94,9.08 C2.3,9.72 1.27,9.74 0.65,9.12 C0.65,9.12 -7.53,0.95 -7.53,0.95 C-7.53,0.95 -4.7,0.94 -4.7,0.94 C-4.7,0.94 1.78,7.42 1.78,7.42 C1.78,7.42 7.11,2.11 7.11,2.11 C7.11,2.11 7.14,2.14 7.14,2.14 C7.14,2.14 8.48,3.49 8.48,3.49 C8.48,3.49 8.5,3.51 8.5,3.51 C8.5,3.51 8.52,3.53 8.52,3.53c " /> + <path + android:name="_R_G_L_2_G_D_1_P_0" + android:fillAlpha="1" + android:fillColor="#ffffff" + android:fillType="nonZero" + android:pathData=" M-8.52 -3.53 C-8.52,-3.53 -2.94,-9.08 -2.94,-9.08 C-2.3,-9.72 -1.27,-9.74 -0.65,-9.12 C-0.65,-9.12 7.53,-0.95 7.53,-0.95 C7.53,-0.95 4.7,-0.94 4.7,-0.94 C4.7,-0.94 -1.78,-7.42 -1.78,-7.42 C-1.78,-7.42 -7.11,-2.11 -7.11,-2.11 C-7.11,-2.11 -7.14,-2.14 -7.14,-2.14 C-7.14,-2.14 -8.48,-3.49 -8.48,-3.49 C-8.48,-3.49 -8.5,-3.51 -8.5,-3.51 C-8.5,-3.51 -8.52,-3.53 -8.52,-3.53c " /> + <path + android:name="_R_G_L_2_G_D_2_P_0" + android:fillAlpha="1" + android:fillColor="#ffffff" + android:fillType="nonZero" + android:pathData=" M7.54 -0.94 C7.54,-0.94 7.54,-0.95 7.54,-0.95 C7.55,-0.94 7.54,-0.94 7.55,-0.94 C7.55,-0.94 7.53,-0.94 7.53,-0.94 C7.53,-0.94 7.52,-0.94 7.52,-0.94 C7.52,-0.94 7.54,-0.94 7.54,-0.94 C7.54,-0.94 7.52,-0.94 7.52,-0.94 C7.52,-0.94 7.54,-0.94 7.54,-0.94c " /> + <path + android:name="_R_G_L_2_G_D_3_P_0" + android:fillAlpha="1" + android:fillColor="#ffffff" + android:fillType="nonZero" + android:pathData=" M-7.54 0.94 C-7.54,0.94 -7.54,0.95 -7.54,0.95 C-7.55,0.94 -7.54,0.94 -7.54,0.94 C-7.54,0.94 -7.53,0.94 -7.53,0.94 C-7.53,0.94 -7.52,0.94 -7.52,0.94 C-7.52,0.94 -7.54,0.94 -7.54,0.94 C-7.54,0.94 -7.52,0.94 -7.52,0.94 C-7.52,0.94 -7.54,0.94 -7.54,0.94c " /> + </group> + <group + android:name="_R_G_L_1_G_N_3_T_0" + android:rotation="0" + android:translateX="12" + android:translateY="12"> + <group + android:name="_R_G_L_1_G_T_1" + android:rotation="360" + android:translateX="-7" + android:translateY="-3.594"> + <group + android:name="_R_G_L_1_G" + android:translateX="6.984" + android:translateY="3.547"> + <path + android:name="_R_G_L_1_G_D_0_P_0" + android:fillAlpha="1" + android:fillColor="#ffffff" + android:fillType="nonZero" + android:pathData=" M-4.6 -1.06 C-4.6,-1.06 -9.55,-1.06 -9.55,-1.06 C-9.55,-1.06 -9.55,-6.01 -9.55,-6.01 C-9.55,-6.01 -7.55,-6 -7.55,-6 C-7.55,-6 -7.51,-3.04 -7.51,-3.04 C-7.51,-3.04 -4.6,-3.05 -4.6,-3.05 C-4.6,-3.05 -4.6,-1.06 -4.6,-1.06c " /> + </group> + </group> + </group> + <group + android:name="_R_G_L_0_G_N_3_T_0" + android:rotation="0" + android:translateX="12" + android:translateY="12"> + <group + android:name="_R_G_L_0_G_T_1" + android:rotation="180" + android:translateX="7.062" + android:translateY="3.312"> + <group + android:name="_R_G_L_0_G" + android:translateX="6.984" + android:translateY="3.547"> + <path + android:name="_R_G_L_0_G_D_0_P_0" + android:fillAlpha="1" + android:fillColor="#ffffff" + android:fillType="nonZero" + android:pathData=" M-4.6 -1.06 C-4.6,-1.06 -9.55,-1.06 -9.55,-1.06 C-9.55,-1.06 -9.55,-6.01 -9.55,-6.01 C-9.55,-6.01 -7.55,-6 -7.55,-6 C-7.55,-6 -7.51,-3.04 -7.51,-3.04 C-7.51,-3.04 -4.6,-3.05 -4.6,-3.05 C-4.6,-3.05 -4.6,-1.06 -4.6,-1.06c " /> + </group> + </group> + </group> + </group> + <group android:name="time_group" /> + </vector> + </aapt:attr> +</animated-vector> diff --git a/packages/SystemUI/res-keyguard/drawable/qs_bluetooth_icon_off.xml b/packages/SystemUI/res-keyguard/drawable/qs_bluetooth_icon_off.xml new file mode 100644 index 000000000000..17a76116db25 --- /dev/null +++ b/packages/SystemUI/res-keyguard/drawable/qs_bluetooth_icon_off.xml @@ -0,0 +1,144 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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. + --> + +<animated-vector + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <aapt:attr name="android:drawable"> + <vector + android:height="24dp" + android:width="24dp" + android:viewportHeight="24" + android:viewportWidth="24"> + <group android:name="_R_G"> + <group android:name="_R_G_L_2_G" + android:translateX="14.125" + android:translateY="12"> + <path + android:name="_R_G_L_2_G_D_0_P_0" + android:fillColor="#ffffff" + android:fillAlpha="1" + android:fillType="nonZero" + android:pathData=" M-1 6.17 C-1,6.17 0.88,4.29 0.88,4.29 C0.88,4.29 -1,2.41 -1,2.41 C-1,2.41 -1,6.17 -1,6.17c M0.88 -4.29 C0.88,-4.29 -1,-6.17 -1,-6.17 C-1,-6.17 -1,-2.41 -1,-2.41 C-1,-2.41 0.88,-4.29 0.88,-4.29c M-2 -10 C-2,-10 3.71,-4.29 3.71,-4.29 C3.71,-4.29 -0.59,0 -0.59,0 C-0.59,0 3.71,4.29 3.71,4.29 C3.71,4.29 -2,10 -2,10 C-2,10 -3,10 -3,10 C-3,10 -3,2.41 -3,2.41 C-3,2.41 -7.59,7 -7.59,7 C-7.59,7 -9.01,5.59 -9.01,5.59 C-9.01,5.59 -3.41,0 -3.41,0 C-3.41,0 -9.01,-5.59 -9.01,-5.59 C-9.01,-5.59 -7.59,-7 -7.59,-7 C-7.59,-7 -3,-2.41 -3,-2.41 C-3,-2.41 -3,-10 -3,-10 C-3,-10 -2,-10 -2,-10c "/> + </group> + <group + android:name="_R_G_L_1_G" + android:translateX="14.125" + android:translateY="12" + android:pivotX="-9.109" + android:scaleX="1" + android:scaleY="1"> + <path + android:name="_R_G_L_1_G_D_0_P_0" + android:fillColor="#ffffff" + android:fillAlpha="1" + android:fillType="nonZero" + android:pathData=" M-9.09 -1.5 C-8.26,-1.5 -7.59,-0.83 -7.59,0 C-7.59,0.83 -8.26,1.5 -9.09,1.5 C-9.91,1.5 -10.59,0.83 -10.59,0 C-10.59,-0.83 -9.91,-1.5 -9.09,-1.5c "/> + </group> + <group + android:name="_R_G_L_0_G" + android:translateX="14.125" + android:translateY="12" + android:pivotX="4.875" + android:scaleX="1" + android:scaleY="1"> + <path + android:name="_R_G_L_0_G_D_0_P_0" + android:fillColor="#ffffff" + android:fillAlpha="1" + android:fillType="nonZero" + android:pathData=" M4.92 -1.5 C5.75,-1.5 6.42,-0.83 6.42,0 C6.42,0.83 5.75,1.5 4.92,1.5 C4.09,1.5 3.42,0.83 3.42,0 C3.42,-0.83 4.09,-1.5 4.92,-1.5c "/> + </group> + </group> + <group android:name="time_group"/> + </vector> + </aapt:attr> + <target android:name="_R_G_L_1_G"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:propertyName="scaleX" + android:duration="150" + android:startOffset="0" + android:valueFrom="1" + android:valueTo="0" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator + android:pathData="M 0.0,0.0 c0.5,0 0.833,0.833 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:propertyName="scaleY" + android:duration="150" + android:startOffset="0" + android:valueFrom="1" + android:valueTo="0" + android:valueType="floatType"> + <aapt:attr + name="android:interpolator"> + <pathInterpolator + android:pathData="M 0.0,0.0 c0.5,0 0.833,0.833 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:propertyName="scaleX" + android:duration="150" + android:startOffset="0" + android:valueFrom="1" + android:valueTo="0" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator + android:pathData="M 0.0,0.0 c0.5,0 0.833,0.833 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:propertyName="scaleY" + android:duration="150" + android:startOffset="0" + android:valueFrom="1" + android:valueTo="0" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator + android:pathData="M 0.0,0.0 c0.5,0 0.833,0.833 1.0,1.0"/> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:propertyName="translateX" + android:duration="150" + android:startOffset="0" + android:valueFrom="0" + android:valueTo="1" + android:valueType="floatType"/> + </set> + </aapt:attr> + </target> +</animated-vector> diff --git a/packages/SystemUI/res-keyguard/drawable/qs_bluetooth_icon_on.xml b/packages/SystemUI/res-keyguard/drawable/qs_bluetooth_icon_on.xml new file mode 100644 index 000000000000..2dba48cf155d --- /dev/null +++ b/packages/SystemUI/res-keyguard/drawable/qs_bluetooth_icon_on.xml @@ -0,0 +1,138 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + ~ 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. + --> + +<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <target android:name="_R_G_L_1_G"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="250" + android:propertyName="scaleX" + android:startOffset="0" + android:valueFrom="0" + android:valueTo="1" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.35,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="250" + android:propertyName="scaleY" + android:startOffset="0" + android:valueFrom="0" + android:valueTo="1" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.35,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="250" + android:propertyName="scaleX" + android:startOffset="0" + android:valueFrom="0" + android:valueTo="1" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.35,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="250" + android:propertyName="scaleY" + android:startOffset="0" + android:valueFrom="0" + android:valueTo="1" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.35,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="267" + android:propertyName="translateX" + android:startOffset="0" + android:valueFrom="0" + android:valueTo="1" + android:valueType="floatType" /> + </set> + </aapt:attr> + </target> + <aapt:attr name="android:drawable"> + <vector + android:width="24dp" + android:height="24dp" + android:viewportHeight="24" + android:viewportWidth="24"> + <group android:name="_R_G"> + <group + android:name="_R_G_L_2_G" + android:translateX="14.125" + android:translateY="12"> + <path + android:name="_R_G_L_2_G_D_0_P_0" + android:fillAlpha="1" + android:fillColor="#ffffff" + android:fillType="nonZero" + android:pathData=" M-1 6.17 C-1,6.17 0.88,4.29 0.88,4.29 C0.88,4.29 -1,2.41 -1,2.41 C-1,2.41 -1,6.17 -1,6.17c M0.88 -4.29 C0.88,-4.29 -1,-6.17 -1,-6.17 C-1,-6.17 -1,-2.41 -1,-2.41 C-1,-2.41 0.88,-4.29 0.88,-4.29c M-2 -10 C-2,-10 3.71,-4.29 3.71,-4.29 C3.71,-4.29 -0.59,0 -0.59,0 C-0.59,0 3.71,4.29 3.71,4.29 C3.71,4.29 -2,10 -2,10 C-2,10 -3,10 -3,10 C-3,10 -3,2.41 -3,2.41 C-3,2.41 -7.59,7 -7.59,7 C-7.59,7 -9.01,5.59 -9.01,5.59 C-9.01,5.59 -3.41,0 -3.41,0 C-3.41,0 -9.01,-5.59 -9.01,-5.59 C-9.01,-5.59 -7.59,-7 -7.59,-7 C-7.59,-7 -3,-2.41 -3,-2.41 C-3,-2.41 -3,-10 -3,-10 C-3,-10 -2,-10 -2,-10c " /> + </group> + <group + android:name="_R_G_L_1_G" + android:pivotX="-9.109" + android:scaleX="0" + android:scaleY="0" + android:translateX="14.125" + android:translateY="12"> + <path + android:name="_R_G_L_1_G_D_0_P_0" + android:fillAlpha="1" + android:fillColor="#ffffff" + android:fillType="nonZero" + android:pathData=" M-9.09 -1.5 C-8.26,-1.5 -7.59,-0.83 -7.59,0 C-7.59,0.83 -8.26,1.5 -9.09,1.5 C-9.91,1.5 -10.59,0.83 -10.59,0 C-10.59,-0.83 -9.91,-1.5 -9.09,-1.5c " /> + </group> + <group + android:name="_R_G_L_0_G" + android:pivotX="4.875" + android:scaleX="0" + android:scaleY="0" + android:translateX="14.125" + android:translateY="12"> + <path + android:name="_R_G_L_0_G_D_0_P_0" + android:fillAlpha="1" + android:fillColor="#ffffff" + android:fillType="nonZero" + android:pathData=" M4.92 -1.5 C5.75,-1.5 6.42,-0.83 6.42,0 C6.42,0.83 5.75,1.5 4.92,1.5 C4.09,1.5 3.42,0.83 3.42,0 C3.42,-0.83 4.09,-1.5 4.92,-1.5c " /> + </group> + </group> + <group android:name="time_group" /> + </vector> + </aapt:attr> +</animated-vector> diff --git a/packages/SystemUI/res-keyguard/drawable/qs_bluetooth_icon_search.xml b/packages/SystemUI/res-keyguard/drawable/qs_bluetooth_icon_search.xml new file mode 100644 index 000000000000..3697769cfa34 --- /dev/null +++ b/packages/SystemUI/res-keyguard/drawable/qs_bluetooth_icon_search.xml @@ -0,0 +1,268 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + ~ 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. + --> + +<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <target android:name="_R_G_L_0_G_D_1_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="167" + android:propertyName="fillAlpha" + android:startOffset="0" + android:valueFrom="0" + android:valueTo="1" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="167" + android:propertyName="fillAlpha" + android:startOffset="167" + android:valueFrom="1" + android:valueTo="1" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="167" + android:propertyName="fillAlpha" + android:startOffset="333" + android:valueFrom="1" + android:valueTo="0" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G_D_2_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="167" + android:propertyName="fillAlpha" + android:startOffset="0" + android:valueFrom="0" + android:valueTo="0" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="167" + android:propertyName="fillAlpha" + android:startOffset="167" + android:valueFrom="0" + android:valueTo="1" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="167" + android:propertyName="fillAlpha" + android:startOffset="333" + android:valueFrom="1" + android:valueTo="1" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="167" + android:propertyName="fillAlpha" + android:startOffset="500" + android:valueFrom="1" + android:valueTo="0" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G_D_3_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="167" + android:propertyName="fillAlpha" + android:startOffset="0" + android:valueFrom="0" + android:valueTo="1" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="167" + android:propertyName="fillAlpha" + android:startOffset="167" + android:valueFrom="1" + android:valueTo="1" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="167" + android:propertyName="fillAlpha" + android:startOffset="333" + android:valueFrom="1" + android:valueTo="0" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G_D_4_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="167" + android:propertyName="fillAlpha" + android:startOffset="0" + android:valueFrom="0" + android:valueTo="0" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="167" + android:propertyName="fillAlpha" + android:startOffset="167" + android:valueFrom="0" + android:valueTo="1" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="167" + android:propertyName="fillAlpha" + android:startOffset="333" + android:valueFrom="1" + android:valueTo="1" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="167" + android:propertyName="fillAlpha" + android:startOffset="500" + android:valueFrom="1" + android:valueTo="0" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="1017" + android:propertyName="translateX" + android:startOffset="0" + android:valueFrom="0" + android:valueTo="1" + android:valueType="floatType" /> + </set> + </aapt:attr> + </target> + <aapt:attr name="android:drawable"> + <vector + android:width="24dp" + android:height="24dp" + android:viewportHeight="24" + android:viewportWidth="24"> + <group android:name="_R_G"> + <group + android:name="_R_G_L_0_G" + android:translateX="14.125" + android:translateY="12"> + <path + android:name="_R_G_L_0_G_D_0_P_0" + android:fillAlpha="1" + android:fillColor="#ffffff" + android:fillType="nonZero" + android:pathData=" M-1 6.17 C-1,6.17 0.88,4.29 0.88,4.29 C0.88,4.29 -1,2.41 -1,2.41 C-1,2.41 -1,6.17 -1,6.17c M0.88 -4.29 C0.88,-4.29 -1,-6.17 -1,-6.17 C-1,-6.17 -1,-2.41 -1,-2.41 C-1,-2.41 0.88,-4.29 0.88,-4.29c M-2 -10 C-2,-10 3.71,-4.29 3.71,-4.29 C3.71,-4.29 -0.59,0 -0.59,0 C-0.59,0 3.71,4.29 3.71,4.29 C3.71,4.29 -2,10 -2,10 C-2,10 -3,10 -3,10 C-3,10 -3,2.41 -3,2.41 C-3,2.41 -7.59,7 -7.59,7 C-7.59,7 -9.01,5.59 -9.01,5.59 C-9.01,5.59 -3.41,0 -3.41,0 C-3.41,0 -9.01,-5.59 -9.01,-5.59 C-9.01,-5.59 -7.59,-7 -7.59,-7 C-7.59,-7 -3,-2.41 -3,-2.41 C-3,-2.41 -3,-10 -3,-10 C-3,-10 -2,-10 -2,-10c " /> + <path + android:name="_R_G_L_0_G_D_1_P_0" + android:fillAlpha="0" + android:fillColor="#ffffff" + android:fillType="nonZero" + android:pathData=" M4.56 2.33 C4.56,2.33 2.24,0.01 2.24,0.01 C2.24,0.01 4.57,-2.31 4.57,-2.31 C4.84,-1.59 5,-0.82 5,0 C5,0.82 4.84,1.61 4.56,2.33c " /> + <path + android:name="_R_G_L_0_G_D_2_P_0" + android:fillAlpha="0" + android:fillColor="#ffffff" + android:fillType="nonZero" + android:pathData=" M6.27 -4.03 C6.27,-4.03 7.53,-5.29 7.53,-5.29 C8.46,-3.77 9,-1.99 9.01,-0.1 C9.01,1.85 8.44,3.67 7.47,5.21 C7.47,5.21 6.27,4.01 6.27,4.01 C6.89,2.81 7.25,1.44 7.25,-0.01 C7.25,-1.46 6.9,-2.82 6.27,-4.03c " /> + <path + android:name="_R_G_L_0_G_D_3_P_0" + android:fillAlpha="0" + android:fillColor="#ffffff" + android:fillType="nonZero" + android:pathData=" M-8.6 -2.33 C-8.6,-2.33 -6.28,-0.01 -6.28,-0.01 C-6.28,-0.01 -8.61,2.31 -8.61,2.31 C-8.88,1.59 -9.04,0.82 -9.04,0 C-9.04,-0.82 -8.88,-1.61 -8.6,-2.33c " /> + <path + android:name="_R_G_L_0_G_D_4_P_0" + android:fillAlpha="0" + android:fillColor="#ffffff" + android:fillType="nonZero" + android:pathData=" M-10.31 4.03 C-10.31,4.03 -11.57,5.29 -11.57,5.29 C-12.5,3.77 -13.04,1.99 -13.05,0.1 C-13.05,-1.85 -12.48,-3.67 -11.51,-5.21 C-11.51,-5.21 -10.31,-4.01 -10.31,-4.01 C-10.93,-2.81 -11.29,-1.44 -11.29,0.01 C-11.29,1.46 -10.94,2.82 -10.31,4.03c " /> + <path + android:name="_R_G_L_0_G_D_5_P_0" + android:fillAlpha="1" + android:fillColor="#000000" + android:fillType="nonZero" + android:pathData=" M-9.09 0 C-9.09,0 -9.09,0 -9.09,0 C-9.09,0 -9.09,0 -9.09,0 C-9.09,0 -9.09,0 -9.09,0 C-9.09,0 -9.09,0 -9.09,0c " /> + <path + android:name="_R_G_L_0_G_D_6_P_0" + android:fillAlpha="1" + android:fillColor="#000000" + android:fillType="nonZero" + android:pathData=" M4.92 0 C4.92,0 4.92,0 4.92,0 C4.92,0 4.92,0 4.92,0 C4.92,0 4.92,0 4.92,0 C4.92,0 4.92,0 4.92,0c " /> + </group> + </group> + <group android:name="time_group" /> + </vector> + </aapt:attr> +</animated-vector> diff --git a/packages/SystemUI/res/drawable/ic_circular_unchecked.xml b/packages/SystemUI/res/drawable/ic_circular_unchecked.xml index 779ab816d925..9b43cf64f116 100644 --- a/packages/SystemUI/res/drawable/ic_circular_unchecked.xml +++ b/packages/SystemUI/res/drawable/ic_circular_unchecked.xml @@ -4,6 +4,6 @@ android:viewportWidth="24" android:viewportHeight="24"> <path - android:fillColor="@color/media_dialog_item_main_content" + android:fillColor="@color/media_dialog_inactive_item_main_content" android:pathData="M12,22q-2.075,0 -3.9,-0.788 -1.825,-0.787 -3.175,-2.137 -1.35,-1.35 -2.137,-3.175Q2,14.075 2,12t0.788,-3.9q0.787,-1.825 2.137,-3.175 1.35,-1.35 3.175,-2.137Q9.925,2 12,2t3.9,0.788q1.825,0.787 3.175,2.137 1.35,1.35 2.137,3.175Q22,9.925 22,12t-0.788,3.9q-0.787,1.825 -2.137,3.175 -1.35,1.35 -3.175,2.137Q14.075,22 12,22zM12,12zM12,20q3.325,0 5.663,-2.337Q20,15.325 20,12t-2.337,-5.662Q15.325,4 12,4T6.338,6.338Q4,8.675 4,12q0,3.325 2.338,5.663Q8.675,20 12,20z"/> </vector> diff --git a/packages/SystemUI/res/drawable/media_output_status_check.xml b/packages/SystemUI/res/drawable/media_output_status_check.xml index 5fbc42b245b8..1b750f8959b9 100644 --- a/packages/SystemUI/res/drawable/media_output_status_check.xml +++ b/packages/SystemUI/res/drawable/media_output_status_check.xml @@ -21,6 +21,6 @@ android:viewportHeight="24" android:tint="?attr/colorControlNormal"> <path - android:fillColor="@color/media_dialog_item_main_content" + android:fillColor="@color/media_dialog_item_status" android:pathData="M9,16.2L4.8,12l-1.4,1.4L9,19 21,7l-1.4,-1.4L9,16.2z"/> </vector> diff --git a/packages/SystemUI/res/drawable/media_output_status_failed.xml b/packages/SystemUI/res/drawable/media_output_status_failed.xml index 0599e239a9ee..05c635833441 100644 --- a/packages/SystemUI/res/drawable/media_output_status_failed.xml +++ b/packages/SystemUI/res/drawable/media_output_status_failed.xml @@ -21,6 +21,6 @@ android:viewportHeight="24" android:tint="?attr/colorControlNormal"> <path - android:fillColor="@color/media_dialog_item_main_content" + android:fillColor="@color/media_dialog_inactive_item_main_content" android:pathData="M11,7h2v2h-2zM11,11h2v6h-2zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z"/> </vector> diff --git a/packages/SystemUI/res/layout/emergency_cryptkeeper_text.xml b/packages/SystemUI/res/layout/emergency_cryptkeeper_text.xml deleted file mode 100644 index 0a1730a72920..000000000000 --- a/packages/SystemUI/res/layout/emergency_cryptkeeper_text.xml +++ /dev/null @@ -1,28 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - ~ 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 - --> - -<com.android.systemui.statusbar.policy.EmergencyCryptkeeperText - xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/emergency_cryptkeeper_text" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:textAppearance="@style/TextAppearance.StatusBar.Clock" - android:paddingStart="6dp" - android:singleLine="true" - android:ellipsize="marquee" - android:gravity="center_vertical|start" - />
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/media_output_dialog.xml b/packages/SystemUI/res/layout/media_output_dialog.xml index 1efb4796b5b7..39c5c4564e19 100644 --- a/packages/SystemUI/res/layout/media_output_dialog.xml +++ b/packages/SystemUI/res/layout/media_output_dialog.xml @@ -137,7 +137,7 @@ style="@style/Widget.Dialog.Button.BorderButton" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="@string/media_output_dialog_button_stop_casting" + android:text="@string/keyboard_key_media_stop" android:visibility="gone"/> <Space diff --git a/packages/SystemUI/res/layout/media_output_list_item.xml b/packages/SystemUI/res/layout/media_output_list_item.xml index b85ea598dbb4..eeb37c7b062d 100644 --- a/packages/SystemUI/res/layout/media_output_list_item.xml +++ b/packages/SystemUI/res/layout/media_output_list_item.xml @@ -83,7 +83,7 @@ android:ellipsize="end" android:maxLines="1" android:fontFamily="@*android:string/config_headlineFontFamilyMedium" - android:textColor="@color/media_dialog_item_main_content" + android:textColor="@color/media_dialog_inactive_item_main_content" android:textSize="16sp"/> <TextView android:id="@+id/subtitle" @@ -91,7 +91,7 @@ android:layout_height="wrap_content" android:ellipsize="end" android:maxLines="1" - android:textColor="@color/media_dialog_item_main_content" + android:textColor="@color/media_dialog_inactive_item_main_content" android:textSize="14sp" android:fontFamily="@*android:string/config_bodyFontFamily" android:visibility="gone"/> @@ -119,24 +119,14 @@ android:importantForAccessibility="no" android:visibility="gone"/> - <LinearLayout - android:id="@+id/end_action_area" - android:visibility="gone" - android:orientation="vertical" - android:layout_width="48dp" - android:layout_height="64dp" - android:layout_gravity="right|center" - android:gravity="center_vertical"> <CheckBox android:id="@+id/check_box" android:layout_width="24dp" android:layout_height="24dp" android:layout_marginEnd="16dp" - android:layout_gravity="right" + android:layout_gravity="right|center" android:button="@drawable/ic_circle_check_box" android:visibility="gone" /> - - </LinearLayout> </FrameLayout> </LinearLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml index deab1ebd6507..f560e6107fb7 100644 --- a/packages/SystemUI/res/layout/status_bar.xml +++ b/packages/SystemUI/res/layout/status_bar.xml @@ -141,11 +141,4 @@ </com.android.keyguard.AlphaOptimizedLinearLayout> </LinearLayout> - <ViewStub - android:id="@+id/emergency_cryptkeeper_text" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout="@layout/emergency_cryptkeeper_text" - /> - </com.android.systemui.statusbar.phone.PhoneStatusBarView> diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index 0cb773531459..de1b008afc0d 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bevestig"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tik op Bevestig om te voltooi"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Ontsluit met gesig. Druk die ontsluitikoon om voort te gaan."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Ontsluit met gesig. Druk om voort te gaan."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Gesig is herken. Druk om voort te gaan."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Gesig is herken. Druk die ontsluitikoon om voort te gaan."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Gestaaf"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Gebruik PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Gebruik patroon"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Swiep op om oop te maak"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Druk die onsluitikoon om oop te maak"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Ontsluit met gesig. Druk die ontsluitikoon om oop te maak."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Ontsluit met gesig. Druk om oop te maak."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Gesig is herken. Druk om oop te maak."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Gesig is herken. Druk die ontsluitikoon om oop te maak."</string> <string name="keyguard_retry" msgid="886802522584053523">"Swiep op om weer te probeer"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Ontsluit om NFC te gebruik"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Hierdie toestel behoort aan jou organisasie"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Wiil jy jou sessie voortsit?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Begin van voor af"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Ja, gaan voort"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Gasmodus"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Jy is in gasmodus"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Voeg nuwe gebruiker by?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Wanneer jy \'n nuwe gebruiker byvoeg, moet daardie persoon hul spasie opstel.\n\nEnige gebruiker kan programme vir al die ander gebruikers opdateer."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"As ’n nuwe gebruiker bygevoeg word, sal gasmodus verlaat word en sal alle programme en data in die huidige gastesessie uitgevee word."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Gebruikerlimiet is bereik"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">Jy kan tot <xliff:g id="COUNT">%d</xliff:g> gebruikers byvoeg.</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Bind nuwe toestel saam"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Maak die program oop om hierdie sessie uit te saai."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Onbekende program"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Hou op uitsaai"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Hoe uitsaai werk"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Saai uit"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Mense in jou omtrek met versoenbare Bluetooth-toestelle kan na die media luister wat jy uitsaai"</string> diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index 4cd2a3d40829..00d9a9fc45bf 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ተረጋግጧል"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ለማጠናቀቅ አረጋግጥን መታ ያድርጉ"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"በመልክ ተከፍቷል። ለመቀጠል የመክፈቻ አዶውን ይጫኑ።"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"በመልክ ተከፍቷል። ለመቀጠል ይጫኑ።"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"መልክ ተለይቶ ታውቋል። ለመቀጠል ይጫኑ።"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"መልክ ተለይቶ ታውቋል። ለመቀጠል የመክፈቻ አዶውን ይጫኑ።"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"የተረጋገጠ"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"ፒን ይጠቀሙ"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ሥርዓተ ጥለትን ተጠቀም"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"ለመክፈት በጣት ወደ ላይ ጠረግ ያድርጉ"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"ለመክፈት የመክፈቻ አዶውን ይጫኑ"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"በመልክ ተከፍቷል። ለመክፈት የመክፈቻ አዶውን ይጫኑ።"</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"በመልክ ተከፍቷል። ለመክፈት ይጫኑ።"</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"መልክ ተለይቶ ታውቋል። ለመክፈት ይጫኑ።"</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"መልክ ተለይቶ ታውቋል። ለመክፈት የመክፈቻ አዶውን ይጫኑ።"</string> <string name="keyguard_retry" msgid="886802522584053523">"እንደገና ለመሞከር ወደ ላይ ይጥረጉ"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFCን ለመጠቀም ይክፈቱ"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ይህ መሣሪያ የድርጅትዎ ነው"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"ክፍለ-ጊዜዎን መቀጠል ይፈልጋሉ?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"እንደገና ጀምር"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"አዎ፣ ቀጥል"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"የእንግዳ ሁነታ"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"በእንግዳ ሁኔታ ውስጥ ነዎት"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"አዲስ ተጠቃሚ ይታከል?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"እርስዎ አንድ አዲስ ተጠቃሚ ሲያክሉ ያ ሰው የራሱ ቦታ ማዘጋጀት አለበት።\n\nማንኛውም ተጠቃሚ መተግበሪያዎችን ለሌሎች ተጠቃሚዎች ሁሉ ሊያዘምን ይችላል።"</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"አዲስ ተጠቃሚ ማከል ከእንግዳ ሁነታ ወጥቶ ሁሉንም መተግበሪያዎች እና ውሂብ አሁን ካለው የእንግዳ ክፍለ ጊዜ ይሰርዛል።"</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"የተጠቃሚ ገደብ ላይ ተደርሷል"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> ተጠቃሚዎች ብቻ ናቸው ሊፈጠሩ የሚችሉት።</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"አዲስ መሣሪያ ያጣምሩ"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"ይህን ክፍለ ጊዜ cast ለማድረግ፣ እባክዎ መተግበሪያውን ይክፈቱ።"</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"የማይታወቅ መተግበሪያ"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Cast ማድረግ አቁም"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ማሰራጨት እንዴት እንደሚሠራ"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"ስርጭት"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"ተኳሃኝ የብሉቱዝ መሣሪያዎች ያላቸው በአቅራቢያዎ ያሉ ሰዎች እርስዎ እያሰራጩት ያሉትን ሚዲያ ማዳመጥ ይችላሉ"</string> diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index 60bf24742a1d..c5408e9d246a 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"تمّ التأكيد."</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"يمكنك النقر على \"تأكيد\" لإكمال المهمة."</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"فُتح القفل عندما تمّ التعرّف على وجهك. للمتابعة، اضغط على رمز فتح القفل."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"تم فتح قفل جهازك عند تقريبه من وجهك. اضغط للمتابعة."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"تم التعرّف على الوجه. اضغط للمتابعة."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"تم التعرّف على الوجه. للمتابعة، اضغط على رمز فتح القفل."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"مصادقة"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"استخدام رقم تعريف شخصي"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"استخدام نقش"</string> @@ -320,6 +323,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"يمكنك الفتح بالتمرير سريعًا لأعلى."</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"اضغط على رمز فتح القفل لفتح قفل الشاشة."</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"فُتح القفل عندما تمّ التعرّف على وجهك. اضغط على رمز فتح القفل لفتحه."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"تم فتح قفل جهازك عند تقريبه من وجهك. اضغط لفتح الجهاز."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"تم التعرّف على الوجه. اضغط لفتح الجهاز."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"تم التعرّف على الوجه. اضغط على رمز فتح القفل لفتح الجهاز."</string> <string name="keyguard_retry" msgid="886802522584053523">"مرِّر سريعًا للأعلى لإعادة المحاولة."</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"افتح قفل الشاشة لاستخدام تقنية NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"هذا الجهاز يخص مؤسستك."</string> @@ -346,6 +352,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"هل تريد متابعة جلستك؟"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"البدء من جديد"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"نعم، متابعة"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"وضع الضيف"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"أنت تستخدِم وضع الضيف."</string> + <string name="user_add_user_title" msgid="4172327541504825032">"هل تريد إضافة مستخدم جديد؟"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"عند إضافة مستخدم جديد، عليه إعداد مساحته.\n\nويُمكن لأي مستخدم تحديث التطبيقات لجميع المستخدمين الآخرين."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"ستؤدي إضافة مُستخدِم جديد إلى الخروج من وضع الضيف وحذف كل التطبيقات والبيانات من جلسة الضيف الحالية."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"تم الوصول إلى أقصى عدد للمستخدمين"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="zero">يمكنك إضافة ما يصل إلى <xliff:g id="COUNT">%d</xliff:g> مستخدم.</item> @@ -859,7 +870,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"إقران جهاز جديد"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"لبث هذه الجلسة، يُرجى فتح التطبيق"</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"تطبيق غير معروف"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"إيقاف البث"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"كيفية عمل البث"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"البث"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"يمكن للأشخاص القريبين منك الذين لديهم أجهزة متوافقة تتضمّن بلوتوث الاستماع إلى الوسائط التي تبثها."</string> diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml index b9ba840f00c5..853ac7a0f8b8 100644 --- a/packages/SystemUI/res/values-as/strings.xml +++ b/packages/SystemUI/res/values-as/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"নিশ্চিত কৰিলে"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"সম্পূৰ্ণ কৰিবলৈ নিশ্চিত কৰক-ত টিপক"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"মুখাৱয়বৰ জৰিয়তে আনলক কৰা হৈছে। অব্যাহত ৰাখিবলৈ আনলক কৰক চিহ্নটোত টিপক।"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"মুখাৱয়বৰ জৰিয়তে আনলক কৰা হৈছে। অব্যাহত ৰাখিবলৈ টিপক।"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"মুখাৱয়ব চিনাক্ত কৰা হৈছে। অব্যাহত ৰাখিবলৈ টিপক।"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"মুখাৱয়ব চিনাক্ত কৰা হৈছে। অব্যাহত ৰাখিবলৈ আনলক কৰক চিহ্নটোত টিপক।"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ কৰা হ’ল"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"পিন ব্যৱহাৰ কৰক"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"আৰ্হি ব্যৱহাৰ কৰক"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"খুলিবলৈ ওপৰলৈ ছোৱাইপ কৰক"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"খুলিবলৈ আনলক কৰক চিহ্নটোত টিপক"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"মুখাৱয়বৰ জৰিয়তে আনলক কৰা হৈছে। খুলিবলৈ আনলক কৰক চিহ্নটোত টিপক।"</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"মুখাৱয়বৰ জৰিয়তে আনলক কৰা হৈছে। খুলিবলৈ টিপক।"</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"মুখাৱয়ব চিনাক্ত কৰা হৈছে। খুলিবলৈ টিপক।"</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"মুখাৱয়ব চিনাক্ত কৰা হৈছে। খুলিবলৈ আনলক কৰক চিহ্নটোত টিপক।"</string> <string name="keyguard_retry" msgid="886802522584053523">"পুনৰ চেষ্টা কৰিবলৈ ওপৰলৈ ছোৱাইপ কৰক"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ব্যৱহাৰ কৰিবলৈ আনলক কৰক"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"এই ডিভাইচটো আপোনাৰ প্ৰতিষ্ঠানৰ"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"আপুনি আপোনাৰ ছেশ্বন অব্যাহত ৰাখিব বিচাৰেনে?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"আকৌ আৰম্ভ কৰক"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"হয়, অব্যাহত ৰাখক"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"অতিথি ম’ড"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"আপুনি অতিথি ম’ডত আছে"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"নতুন ব্যৱহাৰকাৰী যোগ কৰিবনে?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"আপুনি যেতিয়া এজন নতুন ব্যৱহাৰকাৰী যোগ কৰে, তেওঁ নিজৰ স্থান ছেট আপ কৰা প্ৰয়োজন।\n\nযিকোনো ব্যৱহাৰকাৰীয়ে নিজৰ লগতে আন ব্যৱহাৰকাৰীৰো এপ্ আপডে’ট কৰিব পাৰে।"</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"এগৰাকী নতুন ব্যৱহাৰকাৰীক যোগ দিয়াটোৱে অতিথি ম’ডৰ পৰা বাহিৰ কৰিব আৰু বৰ্তমানৰ অতিথিৰ ছেশ্বনটোৰ পৰা আটাইবোৰ এপ্ আৰু ডেটা মচিব।"</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"অধিকতম ব্যৱহাৰকাৰী সৃষ্টি কৰা হ’ল"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="one">আপুনি <xliff:g id="COUNT">%d</xliff:g> জনলৈকে ব্যৱহাৰকাৰী যোগ কৰিব পাৰে।</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"নতুন ডিভাইচ পেয়াৰ কৰক"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"এই ছেশ্বনটো কাষ্ট কৰিবলৈ, অনুগ্ৰহ কৰি এপ্টো খোলক"</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"অজ্ঞাত এপ্"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"কাষ্ট বন্ধ কৰক"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"সম্প্ৰচাৰ কৰাটোৱে কেনেকৈ কাম কৰে"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"সম্প্ৰচাৰ"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"সমিল ব্লুটুথ ডিভাইচৰ সৈতে আপোনাৰ নিকটৱৰ্তী স্থানত থকা লোকসকলে আপুনি সম্প্ৰচাৰ কৰা মিডিয়াটো শুনিব পাৰে"</string> diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml index c0735cc6dec3..0187aa5c6027 100644 --- a/packages/SystemUI/res/values-az/strings.xml +++ b/packages/SystemUI/res/values-az/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Təsdiqləndi"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tamamlamaq üçün \"Təsdiq edin\" seçiminə toxunun"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Üzlə kilidi açılıb. \"Kilidi aç\" ikonasına basıb davam edin."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Üz ilə kiliddən çıxarılıb. Davam etmək üçün basın."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Üz tanınıb. Davam etmək üçün basın."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Üz tanınıb. \"Kiliddən çıxar\" ikonasına basıb davam edin."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Doğrulandı"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN istifadə edin"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Model istifadə edin"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Açmaq üçün yuxarı sürüşdürün"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"\"Kilidi aç\" ikonasına basıb açın"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Üzlə kilidi açılıb. \"Kilidi aç\" ikonasına basıb açın."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Üz ilə kiliddən çıxarılıb. Açmaq üçün basın."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Üz tanınıb. Açmaq üçün basın."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Üz tanınıb. \"Kiliddən çıxar\" ikonasına basıb açın."</string> <string name="keyguard_retry" msgid="886802522584053523">"Yenidən cəhd etmək üçün yuxarı sürüşdürün"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC istifadə etmək üçün kiliddən çıxarın"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Bu cihaz təşkilatınıza məxsusdur"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Sessiya davam etsin?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Yenidən başlayın"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Bəli, davam edin"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Qonaq rejimi"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Qonaq rejimindəsiniz"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Yeni istifadəçi əlavə edilsin?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Yeni istifadəçi əlavə etdiyiniz zaman həmin şəxs öz yerini quraşdırmalıdır. \n\n İstənilən istifadəçi bütün digər istifadəçilərdən olan tətbiqləri güncəlləşdirə bilər."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Yeni istifadəçi əlavə edildikdə qonaq rejimindən çıxılacaq və cari qonaq sessiyasındakı bütün tətbiqlər və data silinəcək."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"İstifadəçi limitinə çatmısınız"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">Maksimum <xliff:g id="COUNT">%d</xliff:g> istifadəçi əlavə edə bilərsiniz.</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Cihaz əlavə edin"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Bu sessiyanı yayımlamaq üçün tətbiqi açın."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Naməlum tətbiq"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Yayımı dayandırın"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Yayım necə işləyir"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Yayım"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Uyğun Bluetooth cihazları olan yaxınlığınızdakı insanlar yayımladığınız medianı dinləyə bilər"</string> diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml index 585b8798798d..899e9346ef65 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potvrđeno"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Dodirnite Potvrdi da biste završili"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Otključano je licem. Pritisnite ikonu otključavanja za nastavak"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Otključano je licem. Pritisnite da biste nastavili."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Lice je prepoznato. Pritisnite da biste nastavili."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Lice prepoznato. Pritisnite ikonu otključavanja za nastavak."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Identitet je potvrđen"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Koristite PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Koristite šablon"</string> @@ -314,6 +317,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Prevucite nagore da biste otvorili"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Pritisnite ikonu otključavanja za otvaranje"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Otključano je licem. Pritisnite ikonu otključavanja za otvaranje"</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Otključano je licem. Pritisnite da biste otvorili."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Lice je prepoznato. Pritisnite da biste otvorili."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Lice prepoznato. Pritisnite ikonu otključavanja za otvaranje."</string> <string name="keyguard_retry" msgid="886802522584053523">"Prevucite nagore da biste probali ponovo"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Otključajte da biste koristili NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Ovaj uređaj pripada organizaciji"</string> @@ -340,6 +346,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Želite li da nastavite sesiju?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Počni iz početka"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Da, nastavi"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Režim gosta"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Koristite režim gosta"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Dodajete novog korisnika?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Kada dodate novog korisnika, ta osoba treba da podesi svoj prostor.\n\nSvaki korisnik može da ažurira aplikacije za sve ostale korisnike."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Dodavanjem novog korisnika izaći ćete iz režima gosta i izbrisaćete sve aplikacije i podatke iz aktuelne sesije gosta."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Dostignut maksimalni broj korisnika"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="one">Možete da dodate najviše <xliff:g id="COUNT">%d</xliff:g> korisnika.</item> @@ -841,7 +852,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Upari novi uređaj"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Da biste prebacivali ovu sesiju, otvorite aplikaciju."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Nepoznata aplikacija"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Zaustavi prebacivanje"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Kako funkcioniše emitovanje"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Emitovanje"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Ljudi u blizini sa kompatibilnim Bluetooth uređajima mogu da slušaju medijski sadržaj koji emitujete"</string> diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml index 08379979bf09..e1f93164e683 100644 --- a/packages/SystemUI/res/values-be/strings.xml +++ b/packages/SystemUI/res/values-be/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Пацверджана"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Націсніце \"Пацвердзіць\", каб завяршыць"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Твар распазнаны. Для працягу націсніце значок разблакіроўкі."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Разблакіравана распазнаваннем твару. Націсніце для працягу."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Твар распазнаны. Націсніце для працягу."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Твар распазнаны. Для працягу націсніце значок разблакіроўкі."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Распазнана"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Увесці PIN-код"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Выкарыстаць узор разблакіроўкі"</string> @@ -316,6 +319,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Каб адкрыць, прагарніце ўверх"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Каб адкрыць, націсніце значок разблакіроўкі"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Твар распазнаны. Для адкрыцця націсніце значок разблакіроўкі"</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Разблакіравана распазнаваннем твару. Націсніце, каб адкрыць."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Твар распазнаны. Націсніце, каб адкрыць."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Твар распазнаны. Для адкрыцця націсніце значок разблакіроўкі."</string> <string name="keyguard_retry" msgid="886802522584053523">"Прагартайце ўверх, каб паўтарыць спробу"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Разблакіруйце, каб выкарыстоўваць NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Гэта прылада належыць вашай арганізацыі"</string> @@ -342,6 +348,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Хочаце працягнуць сеанс?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Пачаць зноў"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Так, працягнуць"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Гасцявы рэжым"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Вы знаходзіцеся ў гасцявым рэжыме"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Дадаць новага карыстальніка?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Пасля стварэння профілю яго трэба наладзіць.\n\nЛюбы карыстальнік прылады можа абнаўляць праграмы ўсіх іншых карыстальнікаў."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Дадаванне новага карыстальніка закрые гасцявы рэжым. Будуць выдалены ўсе праграмы і даныя бягучага гасцявога сеанса."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Дасягнуты ліміт карыстальнікаў"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="one">Можна дадаць <xliff:g id="COUNT">%d</xliff:g> карыстальніка.</item> @@ -847,7 +858,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Спалучыць з новай прыладай"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Для трансляцыі гэтага сеанса адкрыйце праграму."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Невядомая праграма"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Спыніць трансляцыю"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Як адбываецца трансляцыя"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Трансляцыя"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Людзі паблізу, у якіх ёсць прылады з Bluetooth, змогуць праслухваць мультымедыйнае змесціва, якое вы трансліруеце"</string> diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index c9d1e81e7c29..23e41ece32f8 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Потвърдено"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Докоснете „Потвърждаване“ за завършване"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Отключено с лице. Натиснете иконата за отключване, за да продължите."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Отключено с лице. Натиснете, за да продължите."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Лицето бе разпознато. Натиснете, за да продължите."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Лицето бе разпознато. Продължете чрез иконата за отключване."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Удостоверено"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Използване на ПИН"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Използване на фигура"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Прекарайте пръст нагоре, за да отключите"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Натиснете иконата за отключване, за да отворите"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Отключено с лице. Натиснете иконата за отключване, за да отворите."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Отключено с лице. Натиснете за отваряне."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Лицето бе разпознато. Натиснете за отваряне."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Лицето бе разпознато. Отворете чрез иконата за отключване."</string> <string name="keyguard_retry" msgid="886802522584053523">"Плъзнете бързо нагоре, за да опитате отново"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Отключете, за да използвате NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Това устройство принадлежи на организацията ви"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Искате ли да продължите сесията си?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Започване отначало"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Да, продължавам"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Режим на гост"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Вие сте в режим на гост"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Да се добави ли нов потребител?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Когато добавите нов потребител, той трябва да настрои работното си пространство.\n\nВсеки потребител може да актуализира приложенията за всички останали потребители."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"С добавянето на нов потребител ще излезете от режима на гост и ще изтриете всички приложения и данни от текущата сесия като гост."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Достигнахте огранич. за потребители"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">Можете да добавите до <xliff:g id="COUNT">%d</xliff:g> потребители.</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Сдвояване на ново устройство"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"За да предавате тази сесия, моля, отворете приложението."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Неизвестно приложение"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Спиране на предаването"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Как работи предаването"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Предаване"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Хората в близост със съвместими устройства с Bluetooth могат да слушат мултимедията, която предавате"</string> diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index e5920fcdd734..6b6f22184dab 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"কনফার্ম করা হয়েছে"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"সম্পূর্ণ করতে \'কনফার্ম করুন\' বোতামে ট্যাপ করুন"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"ফেসের সাহায্যে আনলক করা হয়েছে। চালিয়ে যাওয়ার জন্য আনলক আইকনে প্রেস করুন।"</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"প্রমাণীকৃত"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"পিন ব্যবহার করুন"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"প্যাটার্ন ব্যবহার করুন"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"খোলার জন্য উপরে সোয়াইপ করুন"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"খোলার জন্য আনলক আইকন প্রেস করুন"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"ফেসের সাহায্যে আনলক করা হয়েছে। খোলার জন্য আনলক আইকন প্রেস করুন।"</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"আবার চেষ্টা করতে উপরের দিকে সোয়াইপ করুন"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ব্যবহার করতে আনলক করুন"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"এই ডিভাইসটি আপনার প্রতিষ্ঠানের"</string> @@ -338,6 +350,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"আপনি কি আপনার সেশনটি চালিয়ে যেতে চান?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"আবার শুরু করুন"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"হ্যাঁ, চালিয়ে যান"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"অতিথি মোড"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"আপনি \'অতিথি মোড\' ব্যবহার করছেন"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"নতুন ব্যবহারকারীকে যোগ করবেন?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"আপনি একজন নতুন ব্যবহারকারী যোগ করলে তাকে তার জায়গা সেট-আপ করে নিতে হবে৷\n\nযেকোনও ব্যবহারকারী অন্য সব ব্যবহারকারীর জন্য অ্যাপ আপডেট করতে পারবেন৷"</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"নতুন ব্যবহারকারী যোগ করার মাধ্যমে \'অতিথি মোড\' ছেড়ে বেরিয়ে আসতে পারবেন এবং বর্তমান অতিথি সেশন থেকে সব অ্যাপ ও ডেটা মুছে যাবে।"</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"আর কোনও প্রোফাইল যোগ করা যাবে না"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="one">আপনি <xliff:g id="COUNT">%d</xliff:g> জন পর্যন্ত ব্যবহারকারীর প্রোফাইল যোগ করতে পারেন।</item> @@ -836,7 +853,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"নতুন ডিভাইস পেয়ার করুন"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"এই সেশন কাস্ট করার জন্য, অ্যাপ খুলুন।"</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"অজানা অ্যাপ"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"কাস্ট করা বন্ধ করুন"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ব্রডকাস্ট কীভাবে কাজ করে"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"সম্প্রচার করুন"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"আশপাশে লোকজন যাদের মানানসই ব্লুটুথ ডিভাইস আছে, তারা আপনার ব্রডকাস্ট করা মিডিয়া শুনতে পারবেন"</string> diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml index 3d84113d1900..41a0dcac36f5 100644 --- a/packages/SystemUI/res/values-bs/strings.xml +++ b/packages/SystemUI/res/values-bs/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potvrđeno"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Dodirnite Potvrdi da završite"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Otključano licem. Pritisnite ikonu za otklj. da nastavite."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Otključano licem. Pritisnite da nastavite."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Lice prepoznato. Pritisnite da nastavite."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Lice prepoznato. Pritisnite ikonu za otklj. da nastavite."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentificirano"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Koristi PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Koristi uzorak"</string> @@ -314,6 +317,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Prevucite da otvorite"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Pritisnite ikonu za otključavanje da otvorite."</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Otključano licem. Pritisnite ikonu za otklj. da otvorite."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Otključano licem. Pritisnite da otvorite."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Lice prepoznato. Pritisnite da otvorite."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Lice prepoznato. Pritisnite ikonu za otklj. da otvorite."</string> <string name="keyguard_retry" msgid="886802522584053523">"Prevucite prema gore da pokušate ponovo"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Otključajte da koristite NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Ovaj uređaj pripada vašoj organizaciji"</string> @@ -340,6 +346,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Želite li nastaviti sesiju?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Počni ispočetka"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Da, nastavi"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Način rada za gosta"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Nalazite se u načinu rada za gosta"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Dodati novog korisnika?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Kada dodate novog korisnika, ta osoba treba postaviti svoj prostor.\n\nSvaki korisnik može ažurirati aplikacije za sve ostale korisnike."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Dodavanjem novog korisnika napustit ćete način rada za gosta i izbrisati sve aplikacije i podatke iz trenutne sesije gosta."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Dostignut limit za broj korisnika"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="one">Možete dodati najviše <xliff:g id="COUNT">%d</xliff:g> korisnika.</item> @@ -841,7 +852,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Uparite novi uređaj"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Da emitirate ovu sesiju, otvorite aplikaciju."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Nepoznata aplikacija"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Zaustavi emitiranje"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Kako funkcionira emitiranje"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Emitirajte"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Osobe u vašoj blizini s kompatibilnim Bluetooth uređajima mogu slušati medijske sadržaje koje emitirate"</string> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index 88228753a1f6..385404074ae6 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmat"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toca Confirma per completar"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"S\'ha desbloquejat amb la cara. Prem la icona per continuar."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autenticat"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Utilitza el PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Utilitza el patró"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Llisca cap amunt per obrir"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Prem la icona de desbloqueig per obrir"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"S\'ha desbloquejat amb la cara. Prem la icona per obrir."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"Llisca cap a dalt per tornar-ho a provar"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloqueja per utilitzar l\'NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Aquest dispositiu pertany a la teva organització"</string> @@ -338,6 +350,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Vols continuar amb la sessió?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Torna a començar"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Sí, continua"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Mode de convidat"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Estàs en mode de convidat"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Vols afegir un usuari nou?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Quan s\'afegeix un usuari nou, aquest usuari ha de configurar-se l\'espai.\n\nQualsevol usuari pot actualitzar les aplicacions de la resta d\'usuaris."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"En afegir un usuari nou, se sortirà del mode de convidat i se suprimiran totes les aplicacions i dades de la sessió de convidat actual."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"S\'ha assolit el límit d\'usuaris"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">Pots afegir fins a <xliff:g id="COUNT">%d</xliff:g> usuaris.</item> @@ -836,7 +853,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Vincula un dispositiu nou"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Per emetre aquesta sessió, obre l\'aplicació."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Aplicació desconeguda"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Atura l\'emissió"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Com funciona l\'emissió"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Emet"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Les persones properes amb dispositius Bluetooth compatibles poden escoltar el contingut multimèdia que emets"</string> diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index 820749f71d42..e9107d08805a 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potvrzeno"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Ověření dokončíte klepnutím na Potvrdit"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Odemknuto obličejem. Klepněte na ikonu odemknutí."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Odemknuto obličejem. Pokračujte stisknutím."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Obličej rozpoznán. Pokračujte stisknutím."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Obličej rozpoznán. Klepněte na ikonu odemknutí."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Ověřeno"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Použít kód PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Použít gesto"</string> @@ -316,6 +319,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Otevřete přejetím prstem nahoru"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Otevřete klepnutím na ikonu odemknutí"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Odemknuto obličejem. Klepněte na ikonu odemknutí."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Odemknuto obličejem. Stisknutím otevřete."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Obličej rozpoznán. Stisknutím otevřete."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Obličej rozpoznán. Klepněte na ikonu odemknutí."</string> <string name="keyguard_retry" msgid="886802522584053523">"Přejetím nahoru to zkusíte znovu"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC vyžaduje odemknutou obrazovku"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Toto zařízení patří vaší organizaci"</string> @@ -342,6 +348,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Chcete v relaci pokračovat?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Začít znovu"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Ano, pokračovat"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Režim hosta"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Jste v režimu hosta"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Přidat nového uživatele?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Když přidáte nového uživatele, musí si nastavit vlastní prostor.\n\nJakýkoli uživatel může aktualizovat aplikace všech ostatních uživatelů."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Přidáním nového uživatele ukončíte režim hosta a smažete všechny aplikace a data z aktuální relace hosta."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Bylo dosaženo limitu uživatelů"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="few">Lze přidat až <xliff:g id="COUNT">%d</xliff:g> uživatele.</item> @@ -847,7 +858,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Spárovat nové zařízení"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Pokud chcete odesílat relaci, otevřete aplikaci."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Neznámá aplikace"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Zastavit odesílání"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Jak vysílání funguje"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Vysílání"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Lidé ve vašem okolí s kompatibilními zařízeními Bluetooth mohou poslouchat média, která vysíláte"</string> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index 135b480a3015..0e0311384981 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bekræftet"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tryk på Bekræft for at udføre"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Låst op vha. ansigt. Tryk på oplåsningsikonet for at fortsætte."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Låst op ved hjælp af ansigt. Tryk for at fortsætte."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Ansigt genkendt. Tryk for at fortsætte."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Ansigt genkendt. Tryk på oplåsningsikonet for at fortsætte."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Godkendt"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Brug pinkode"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Brug mønster"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Stryg opad for at åbne"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Tryk på oplåsningsikonet for at åbne"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Låst op vha. ansigt. Tryk på oplåsningsikonet for at åbne."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Låst op ved hjælp af ansigt. Tryk for at åbne."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Ansigt genkendt. Tryk for at åbne."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Ansigt genkendt. Tryk på oplåsningsikonet for at åbne."</string> <string name="keyguard_retry" msgid="886802522584053523">"Stryg opad for at prøve igen"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Lås op for at bruge NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Denne enhed tilhører din organisation"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Vil du fortsætte din session?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Start forfra"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Ja, fortsæt"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Gæstetilstand"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Gæstetilstand er aktiveret"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Vil du tilføje en ny bruger?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Når du tilføjer en ny bruger, skal personen konfigurere sit område.\n\nAlle brugere kan opdatere apps for alle de andre brugere."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Hvis du tilføjer en ny bruger, deaktiveres gæstetilstanden, og alle apps og data slettes fra den aktuelle gæstesession."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Grænsen for antal brugere er nået"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="one">Du kan tilføje op til <xliff:g id="COUNT">%d</xliff:g> bruger.</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Par ny enhed"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Åbn appen for at caste denne session."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Ukendt app"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Stop med at caste"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Sådan fungerer udsendelser"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Udsendelse"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Personer i nærheden, som har kompatible Bluetooth-enheder, kan lytte til det medie, du udsender"</string> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index 50061fb75849..59e79ec6a7fe 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bestätigt"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Zum Abschließen auf \"Bestätigen\" tippen"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Gerät mit dem Gesicht entsperrt. Tippe auf das Symbol „Entsperren“, um fortzufahren."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Authentifiziert"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN verwenden"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Muster verwenden"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Zum Öffnen nach oben wischen"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Tippe zum Öffnen auf das Symbol „Entsperren“"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Gerät mit dem Gesicht entsperrt. Tippe zum Öffnen auf das Symbol „Entsperren“."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"Zum Wiederholen nach oben wischen"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Zur Verwendung von NFC entsperren"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Dieses Gerät gehört deiner Organisation"</string> @@ -338,6 +350,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Möchtest du deine Sitzung fortsetzen?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Neu starten"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Ja, weiter"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Gastmodus"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Du befindest dich im Gastmodus"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Neuen Nutzer hinzufügen?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Wenn du einen neuen Nutzer hinzufügst, muss dieser seinen Bereich einrichten.\n\nJeder Nutzer kann Apps für alle anderen Nutzer aktualisieren."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Durch Hinzufügen eines neuen Nutzers wird der Gastmodus beendet und alle Apps und Daten der aktuellen Gastsitzung werden gelöscht."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Nutzerlimit erreicht"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">Du kannst bis zu <xliff:g id="COUNT">%d</xliff:g> Nutzer hinzufügen.</item> @@ -836,7 +853,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Neues Gerät koppeln"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Öffne zum Streamen dieser Sitzung die App."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Unbekannte App"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Streaming beenden"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Funktionsweise von Nachrichten an alle"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Nachricht an alle"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Personen, die in der Nähe sind und kompatible Bluetooth-Geräten haben, können sich die Medien anhören, die du per Nachricht an alle sendest"</string> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index d82a28cad763..ffc72be3f80e 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Επιβεβαιώθηκε"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Πατήστε Επιβεβαίωση για ολοκλήρωση"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Ξεκλ. με αναγν. προσώπου. Πατ. το εικον. ξεκλ. για συνέχεια."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Ξεκλείδωμα με αναγνώριση προσώπου. Πατήστε για συνέχεια."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Το πρόσωπο αναγνωρίστηκε. Πατήστε για συνέχεια."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Το πρόσωπο αναγνωρ. Πατήστε το εικον. ξεκλειδ. για συνέχεια."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Ολοκληρώθηκε ο έλεγχος ταυτότητας"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Χρήση PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Χρήση μοτίβου"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Σύρετε προς τα επάνω για άνοιγμα"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Πατήστε το εικονίδιο ξεκλειδώματος για άνοιγμα"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Ξεκλ. με αναγν. προσώπου. Πατ. το εικον. ξεκλ. για άνοιγμα."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Ξεκλείδωμα με αναγνώριση προσώπου. Πατήστε για άνοιγμα."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Το πρόσωπο αναγνωρίστηκε. Πατήστε για άνοιγμα."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Το πρόσωπο αναγνωρ. Πατήστ. το εικον. ξεκλειδ. για άνοιγμα."</string> <string name="keyguard_retry" msgid="886802522584053523">"Σύρετε προς τα πάνω για να δοκιμάσετε ξανά"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Ξεκλείδωμα για χρήση του NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Αυτή η συσκευή ανήκει στον οργανισμό σας."</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Θέλετε να συνεχίσετε την περίοδο σύνδεσής σας;"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Έναρξη από την αρχή"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Ναι, συνέχεια"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Λειτουργία επισκέπτη"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Βρίσκεστε σε λειτουργία επισκέπτη"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Προσθήκη νέου χρήστη;"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Κατά την προσθήκη ενός νέου χρήστη, αυτός θα πρέπει να ρυθμίσει τον χώρο του.\n\nΟποιοσδήποτε χρήστης μπορεί να ενημερώσει τις εφαρμογές για όλους τους άλλους χρήστες."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Με την προσθήκη νέου χρήστη θα γίνει έξοδος από τη λειτουργία επισκέπτη και θα διαγραφούν όλες οι εφαρμογές και τα δεδομένα από την τρέχουσα περίοδο σύνδεσης επισκέπτη."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Συμπληρώθηκε το όριο χρηστών"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">Μπορείτε να προσθέσετε έως <xliff:g id="COUNT">%d</xliff:g> χρήστες.</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Σύζευξη νέας συσκευής"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Για μετάδοση της περιόδου σύνδεσης, ανοίξτε την εφαρμογή."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Άγνωστη εφαρμογή"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Διακοπή μετάδοσης"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Πώς λειτουργεί η μετάδοση"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Μετάδοση"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Οι άνθρωποι με συμβατές συσκευές Bluetooth που βρίσκονται κοντά σας μπορούν να ακούσουν το μέσο που μεταδίδετε."</string> diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml index 2ca4d809fe58..93ae8da3b3f2 100644 --- a/packages/SystemUI/res/values-en-rAU/strings.xml +++ b/packages/SystemUI/res/values-en-rAU/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmed"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tap Confirm to complete"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Unlocked by face. Press the unlock icon to continue."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Unlocked by face. Press to continue."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Face recognised. Press to continue."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Face recognised. Press the unlock icon to continue."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Authenticated"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Use PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Use pattern"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Swipe up to open"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Press the unlock icon to open"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Unlocked by face. Press the unlock icon to open."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Unlocked by face. Press to open."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Face recognised. Press to open."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Face recognised. Press the unlock icon to open."</string> <string name="keyguard_retry" msgid="886802522584053523">"Swipe up to try again"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Unlock to use NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"This device belongs to your organisation"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Do you want to continue your session?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Start again"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Yes, continue"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Guest mode"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"You are in guest mode"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Add new user?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"When you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Adding a new user will exit guest mode and delete all apps and data from the current guest session."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"User limit reached"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">You can add up to <xliff:g id="COUNT">%d</xliff:g> users.</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Pair new device"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"To cast this session, please open the app."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Unknown app"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Stop casting"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"How broadcasting works"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Broadcast"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"People near you with compatible Bluetooth devices can listen to the media that you\'re broadcasting"</string> diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml index d7a4dece9140..7d6149d8d791 100644 --- a/packages/SystemUI/res/values-en-rCA/strings.xml +++ b/packages/SystemUI/res/values-en-rCA/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmed"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tap Confirm to complete"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Unlocked by face. Press the unlock icon to continue."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Unlocked by face. Press to continue."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Face recognised. Press to continue."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Face recognised. Press the unlock icon to continue."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Authenticated"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Use PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Use pattern"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Swipe up to open"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Press the unlock icon to open"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Unlocked by face. Press the unlock icon to open."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Unlocked by face. Press to open."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Face recognised. Press to open."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Face recognised. Press the unlock icon to open."</string> <string name="keyguard_retry" msgid="886802522584053523">"Swipe up to try again"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Unlock to use NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"This device belongs to your organisation"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Do you want to continue your session?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Start again"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Yes, continue"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Guest mode"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"You are in guest mode"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Add new user?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"When you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Adding a new user will exit guest mode and delete all apps and data from the current guest session."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"User limit reached"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">You can add up to <xliff:g id="COUNT">%d</xliff:g> users.</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Pair new device"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"To cast this session, please open the app."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Unknown app"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Stop casting"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"How broadcasting works"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Broadcast"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"People near you with compatible Bluetooth devices can listen to the media that you\'re broadcasting"</string> diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml index 2ca4d809fe58..93ae8da3b3f2 100644 --- a/packages/SystemUI/res/values-en-rGB/strings.xml +++ b/packages/SystemUI/res/values-en-rGB/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmed"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tap Confirm to complete"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Unlocked by face. Press the unlock icon to continue."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Unlocked by face. Press to continue."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Face recognised. Press to continue."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Face recognised. Press the unlock icon to continue."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Authenticated"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Use PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Use pattern"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Swipe up to open"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Press the unlock icon to open"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Unlocked by face. Press the unlock icon to open."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Unlocked by face. Press to open."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Face recognised. Press to open."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Face recognised. Press the unlock icon to open."</string> <string name="keyguard_retry" msgid="886802522584053523">"Swipe up to try again"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Unlock to use NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"This device belongs to your organisation"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Do you want to continue your session?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Start again"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Yes, continue"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Guest mode"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"You are in guest mode"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Add new user?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"When you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Adding a new user will exit guest mode and delete all apps and data from the current guest session."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"User limit reached"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">You can add up to <xliff:g id="COUNT">%d</xliff:g> users.</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Pair new device"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"To cast this session, please open the app."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Unknown app"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Stop casting"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"How broadcasting works"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Broadcast"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"People near you with compatible Bluetooth devices can listen to the media that you\'re broadcasting"</string> diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml index 2ca4d809fe58..93ae8da3b3f2 100644 --- a/packages/SystemUI/res/values-en-rIN/strings.xml +++ b/packages/SystemUI/res/values-en-rIN/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmed"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tap Confirm to complete"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Unlocked by face. Press the unlock icon to continue."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Unlocked by face. Press to continue."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Face recognised. Press to continue."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Face recognised. Press the unlock icon to continue."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Authenticated"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Use PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Use pattern"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Swipe up to open"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Press the unlock icon to open"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Unlocked by face. Press the unlock icon to open."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Unlocked by face. Press to open."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Face recognised. Press to open."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Face recognised. Press the unlock icon to open."</string> <string name="keyguard_retry" msgid="886802522584053523">"Swipe up to try again"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Unlock to use NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"This device belongs to your organisation"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Do you want to continue your session?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Start again"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Yes, continue"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Guest mode"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"You are in guest mode"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Add new user?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"When you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Adding a new user will exit guest mode and delete all apps and data from the current guest session."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"User limit reached"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">You can add up to <xliff:g id="COUNT">%d</xliff:g> users.</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Pair new device"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"To cast this session, please open the app."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Unknown app"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Stop casting"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"How broadcasting works"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Broadcast"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"People near you with compatible Bluetooth devices can listen to the media that you\'re broadcasting"</string> diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml index be94028c3381..edb738fea977 100644 --- a/packages/SystemUI/res/values-en-rXC/strings.xml +++ b/packages/SystemUI/res/values-en-rXC/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmed"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tap Confirm to complete"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Unlocked by face. Press the unlock icon to continue."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Unlocked by face. Press to continue."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Face recognized. Press to continue."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Face recognized. Press the unlock icon to continue."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Authenticated"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Use PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Use pattern"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Swipe up to open"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Press the unlock icon to open"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Unlocked by face. Press the unlock icon to open."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Unlocked by face. Press to open."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Face recognized. Press to open."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Face recognized. Press the unlock icon to open."</string> <string name="keyguard_retry" msgid="886802522584053523">"Swipe up to try again"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Unlock to use NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"This device belongs to your organization"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Do you want to continue your session?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Start over"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Yes, continue"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Guest mode"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"You are in guest mode"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Add new user?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"When you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">"\n\nAdding a new user will exit guest mode and delete all apps and data from the current guest session."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"User limit reached"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">You can add up to <xliff:g id="COUNT">%d</xliff:g> users.</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Pair new device"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"To cast this session, please open the app."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Unknown app"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Stop casting"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"How broadcasting works"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Broadcast"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"People near you with compatible Bluetooth devices can listen to the media you\'re broadcasting"</string> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index ec3c79a562db..d2ad33e4c94c 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmado"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Presiona Confirmar para completar"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Desbloqueo con rostro. Presiona ícono desbl. para continuar."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Desbloqueo con rostro. Presiona para continuar."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Rostro reconocido. Presiona para continuar."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Rostro reconocido. Presiona el desbloqueo para continuar."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autenticado"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Usar PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Usar patrón"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Desliza el dedo hacia arriba para abrir"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Presiona el ícono de desbloquear para abrir"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Desbloqueo con rostro. Presiona ícono desbloq. para abrir."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Desbloqueo con rostro. Presiona para abrir."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Rostro reconocido. Presiona para abrir."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Rostro reconocido. Presiona el desbloqueo para abrir."</string> <string name="keyguard_retry" msgid="886802522584053523">"Desliza el dedo hacia arriba para volver a intentarlo"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloquea el dispositivo para usar NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertenece a tu organización"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"¿Quieres retomar la sesión?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Volver a empezar"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Sí, continuar"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Modo de Invitado"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Estás en el modo de invitado"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"¿Agregar usuario nuevo?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Cuando agregas un nuevo usuario, esa persona debe configurar su espacio.\n\nCualquier usuario puede actualizar las aplicaciones del resto de los usuarios."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Si agregas un usuario nuevo, se desactivará el modo de invitado y se borrarán todas las apps y los datos de la sesión de invitado actual."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Alcanzaste el límite de usuarios"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">Puedes agregar hasta <xliff:g id="COUNT">%d</xliff:g> usuarios.</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Vincular dispositivo nuevo"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Para transmitir esta sesión, abre la app"</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"App desconocida"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Detener transmisión"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Cómo funciona la transmisión"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Transmisión"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Las personas cercanas con dispositivos Bluetooth compatibles pueden escuchar el contenido multimedia que transmites"</string> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index 98394056eefc..b05555a5b900 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmada"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toca Confirmar para completar la acción"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Desbloqueado con datos faciales. Pulsa el icono desbloquear para continuar."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Se ha autenticado"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Usar PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Usar patrón"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Desliza el dedo hacia arriba para abrir"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Pulsa el icono desbloquear para abrir"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Desbloqueado con datos faciales. Pulsa el icono desbloquear para abrir."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"Desliza el dedo hacia arriba para volverlo a intentar"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloquea para usar el NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertenece a tu organización"</string> @@ -338,6 +350,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"¿Quieres continuar con la sesión?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Volver a empezar"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Sí, continuar"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Modo invitados"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Estás en modo invitados"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"¿Añadir nuevo usuario?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Al añadir un nuevo usuario, este debe configurar su espacio.\n\nCualquier usuario puede actualizar las aplicaciones del resto de usuarios."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Si añades un usuario nuevo, saldrás del modo invitados y se eliminarán todas las aplicaciones y datos de la sesión de invitado actual."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Has alcanzado el límite de usuarios"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">Puedes añadir hasta <xliff:g id="COUNT">%d</xliff:g> usuarios.</item> @@ -836,7 +853,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Emparejar nuevo dispositivo"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Para enviar esta sesión, abre la aplicación."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Aplicación desconocida"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Dejar de enviar contenido"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Cómo funciona la emisión"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Emisión"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Las personas cercanas con dispositivos Bluetooth compatibles pueden escuchar el contenido multimedia que emites"</string> diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml index 42842fca72e6..9e7e13547e77 100644 --- a/packages/SystemUI/res/values-et/strings.xml +++ b/packages/SystemUI/res/values-et/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Kinnitatud"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Lõpuleviimiseks puudutage nuppu Kinnita"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Avati näoga. Jätkamiseks vajutage avamise ikooni."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autenditud"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Kasuta PIN-koodi"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Kasuta mustrit"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Pühkige avamiseks üles"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Avamiseks vajutage avamise ikooni"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Avati näoga. Avamiseks vajutage avamise ikooni."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"Uuesti proovimiseks pühkige üles"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC kasutamiseks avage."</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"See seade kuulub teie organisatsioonile"</string> @@ -338,6 +350,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Kas soovite seansiga jätkata?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Alusta uuesti"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Jah, jätka"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Külalisrežiim"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Olete külalisrežiimis"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Kas lisada uus kasutaja?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Kui lisate uue kasutaja, siis peab ta seadistama oma ruumi.\n\nIga kasutaja saab värskendada rakendusi kõigi kasutajate jaoks."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Uue kasutaja lisamisel suletakse külalisrežiim ning praeguse külastajaseansi rakendused ja andmed kustutatakse."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Kasutajate limiit on täis"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">Võite lisada kuni <xliff:g id="COUNT">%d</xliff:g> kasutajat.</item> @@ -836,7 +853,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Uue seadme sidumine"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Selle seansi ülekandmiseks avage rakendus."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Tundmatu rakendus"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Lõpeta ülekanne"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Kuidas ülekandmine toimib?"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Ülekanne"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Teie läheduses olevad inimesed, kellel on ühilduvad Bluetooth-seadmed, saavad kuulata teie ülekantavat meediat"</string> diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml index 53c3698697d7..5a05189144ac 100644 --- a/packages/SystemUI/res/values-eu/strings.xml +++ b/packages/SystemUI/res/values-eu/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Berretsita"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Amaitzeko, sakatu \"Berretsi\""</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Aurpegiaren bidez desblokeatu da. Aurrera egiteko, sakatu desblokeatzeko ikonoa."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentifikatuta"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Erabili PINa"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Erabili eredua"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Pasatu hatza gora irekitzeko"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Irekitzeko, sakatu desblokeatzeko ikonoa"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Aurpegiaren bidez desblokeatu da. Irekitzeko, sakatu desblokeatzeko ikonoa."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"Berriro saiatzeko, pasatu hatza gora"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desblokea ezazu NFC erabiltzeko"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Gailu hau zure erakundearena da"</string> @@ -338,6 +350,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Saioarekin jarraitu nahi duzu?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Hasi berriro"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Bai, jarraitu"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Gonbidatu modua"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Gonbidatu moduan zaude"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Beste erabiltzaile bat gehitu?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Erabiltzaile bat gehitzen duzunean, erabiltzaile horrek bere eremua konfiguratu beharko du.\n\nEdozein erabiltzailek egunera ditzake beste erabiltzaile guztien aplikazioak."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Beste erabiltzaile bat gehituz gero, gonbidatu modua itxiko da eta oraingo gonbidatuentzako saioko aplikazio eta datu guztiak ezabatuko dira."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Erabiltzaile-mugara iritsi zara"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">Gehienez, <xliff:g id="COUNT">%d</xliff:g> erabiltzaile gehi ditzakezu.</item> @@ -836,7 +853,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Parekatu beste gailu batekin"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Saioa ireki nahi baduzu, ireki aplikazioa."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Aplikazio ezezaguna"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Utzi igortzeari"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Nola funtzionatzen dute iragarpenek?"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Iragarri"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Bluetooth bidezko gailu bateragarriak dituzten inguruko pertsonek iragartzen ari zaren multimedia-edukia entzun dezakete"</string> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index 38b1f9fcb8c4..c02b2955cc28 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"تأیید شد"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"برای تکمیل، روی تأیید ضربه بزنید"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"قفلْ با چهره باز شد. برای ادامه، نماد قفلگشایی را فشار دهید."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"قفلْ با چهره باز شد. برای ادامه، فشار دهید."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"چهره شناسایی شد. برای ادامه، فشار دهید."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"چهره شناسایی شد. برای ادامه، نماد قفلگشایی را فشار دهید."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"راستیآزماییشده"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"استفاده از پین"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"استفاده از الگو"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"برای باز کردن، انگشتتان را تند بهبالا بکشید"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"برای باز کردن، نماد قفلگشایی را فشار دهید"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"قفلْ با چهره باز شد. برای باز کردن، نماد قفلگشایی را فشار دهید."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"قفلْ با چهره باز شد. برای باز کردن، فشار دهید."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"چهره شناسایی شد. برای باز کردن، فشار دهید."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"چهره شناسایی شد. برای باز کردن، نماد قفلگشایی را فشار دهید."</string> <string name="keyguard_retry" msgid="886802522584053523">"برای امتحان مجدد، انگشتتان را تند بهبالا بکشید"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"برای استفاده از NFC، قفل را باز کنید"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"این دستگاه به سازمان شما تعلق دارد"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"آیا میخواهید جلسهتان را ادامه دهید؟"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"شروع مجدد"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"بله، ادامه داده شود"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"حالت مهمان"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"در حالت مهمان هستید"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"کاربر جدیدی اضافه میکنید؟"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"وقتی کاربر جدیدی اضافه میکنید آن فرد باید فضای خودش را تنظیم کند.\n\nهر کاربری میتواند برنامهها را برای همه کاربران دیگر بهروزرسانی کند."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"با افزودن کاربر جدید، از حالت مهمان خارج خواهید شد و همه برنامهها و دادهها از جلسه مهمان کنونی حذف خواهند شد."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"به تعداد مجاز تعداد کاربر رسیدهاید"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="one">میتوانید حداکثر <xliff:g id="COUNT">%d</xliff:g> کاربر اضافه کنید.</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"مرتبط کردن دستگاه جدید"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"برای ارسال محتوای این جلسه، لطفاً برنامه را باز کنید."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"برنامه ناشناس"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"توقف ارسال محتوا"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"همهفرتستی چطور کار میکند"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"همهفرستی"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"افرادی که در اطرافتان دستگاههای Bluetooth سازگار دارند میتوانند به رسانهای که همهفرستی میکنید گوش کنند"</string> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index c10bfcb7e362..a90caf2977e4 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Vahvistettu"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Valitse lopuksi Vahvista"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Avattu kasvojen avulla. Jatka lukituksen avauskuvakkeella."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Avattu kasvojen avulla. Jatka painamalla."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Kasvot tunnistettu. Jatka painamalla."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Kasvot tunnistettu. Jatka lukituksen avauskuvakkeella."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Todennettu"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Käytä PIN-koodia"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Käytä kuviota"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Avaa pyyhkäisemällä ylös"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Jatka painamalla lukituksen avauskuvaketta."</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Avattu kasvojen avulla. Jatka lukituksen avauskuvakkeella."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Avattu kasvojen avulla. Avaa painamalla."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Kasvot tunnistettu. Avaa painamalla."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Kasvot tunnistettu. Jatka lukituksen avauskuvakkeella."</string> <string name="keyguard_retry" msgid="886802522584053523">"Yritä uudelleen pyyhkäisemällä ylös"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Avaa lukitus, jotta voit käyttää NFC:tä"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Organisaatiosi omistaa tämän laitteen"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Haluatko jatkaa istuntoa?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Aloita alusta"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Kyllä, haluan jatkaa"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Vierastila"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Olet vierastilassa"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Lisätäänkö uusi käyttäjä?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Kun lisäät uuden käyttäjän, hänen tulee määrittää oman tilansa asetukset.\n\nKaikki käyttäjät voivat päivittää sovelluksia muille käyttäjille."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Uuden käyttäjän lisääminen poistaa sinut vierastilasta. Kaikki sovellukset ja data poistetaan myös samalla nykyisestä vierailija-käyttökerrasta."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Käyttäjäraja saavutettu"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">Voit lisätä korkeintaan <xliff:g id="COUNT">%d</xliff:g> käyttäjää.</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Muodosta uusi laitepari"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Jos haluat striimata tämän käyttökerran, avaa sovellus."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Tuntematon sovellus"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Lopeta striimaus"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Miten lähetys toimii"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Lähetys"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Lähistöllä olevat ihmiset, joilla on yhteensopiva Bluetooth-laite, voivat kuunnella lähettämääsi mediaa"</string> diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index 75e48690c1c2..00fa3f8c3d65 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmé"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Touchez Confirmer pour terminer"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Déverrouillé avec le visage. Appuyez Déverrouiller pour cont."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Authentifié"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Utiliser un NIP"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Utiliser un schéma"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Balayez l\'écran vers le haut pour ouvrir"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Appuyez sur l\'icône Déverrouiller pour ouvrir"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Déverrouillé avec le visage. Appuyez Déverrouiller pour ouvrir"</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"Balayez l\'écran vers le haut pour réessayer"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Déverrouillez l\'écran pour utiliser la CCP"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Cet appareil appartient à votre organisation"</string> @@ -338,6 +350,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Voulez-vous poursuivre la session?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Recommencer"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Oui, continuer"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Mode Invité"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Vous êtes en mode Invité"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Ajouter un utilisateur?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Lorsque vous ajoutez un utilisateur, celui-ci doit configurer son espace.\n\nTout utilisateur peut mettre à jour les applications pour tous les autres utilisateurs."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"L\'ajout d\'un nouvel utilisateur aura pour effet de quitter le mode Invité ainsi que de supprimer toutes les applications et données de la session d\'invité en cours."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Limite d\'utilisateurs atteinte"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="one">Vous pouvez ajouter jusqu\'à <xliff:g id="COUNT">%d</xliff:g> utilisateur.</item> @@ -836,7 +853,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Associer un autre appareil"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Pour diffuser cette session, veuillez ouvrir l\'application."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Application inconnue"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Arrêter la diffusion"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Fonctionnement de la diffusion"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Diffusion"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Les personnes à proximité disposant d\'appareils Bluetooth compatibles peuvent écouter le contenu multimédia que vous diffusez"</string> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index 8854de269557..4418e89b3b53 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmé"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Appuyez sur \"Confirmer\" pour terminer"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Déverrouillé par visage. Appuyez sur icône déverrouillage pour continuer."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Déverrouillé par visage. Appuyez pour continuer."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Visage reconnu. Appuyez pour continuer."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Visage reconnu. Appuyez sur l\'icône de déverrouillage pour continuer."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Authentifié"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Utiliser un code PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Utiliser un schéma"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Balayer vers le haut pour ouvrir"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Appuyez sur l\'icône de déverrouillage pour ouvrir"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Déverrouillé par visage. Appuyez sur icône déverrouillage pour ouvrir."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Déverrouillé par visage. Appuyez pour ouvrir."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Visage reconnu. Appuyez pour ouvrir."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Visage reconnu. Appuyez sur l\'icône de déverrouillage pour ouvrir."</string> <string name="keyguard_retry" msgid="886802522584053523">"Balayez l\'écran vers le haut pour réessayer"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Déverrouillez l\'écran pour pouvoir utiliser NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Cet appareil appartient à votre organisation"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Voulez-vous poursuivre la dernière session ?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Non, nouvelle session"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Oui, continuer"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Mode Invité"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Vous êtes en mode Invité"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Ajouter un utilisateur ?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Lorsque vous ajoutez un utilisateur, celui-ci doit configurer son espace.\n\nN\'importe quel utilisateur peut mettre à jour les applications pour tous les autres utilisateurs."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Si vous ajoutez un utilisateur, le mode Invité sera désactivé et toutes les applis et les données de la session Invité actuelle seront supprimées."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Limite nombre utilisateurs atteinte"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="one">Vous pouvez ajouter <xliff:g id="COUNT">%d</xliff:g> profil utilisateur.</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Associer un nouvel appareil"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Pour caster cette session, veuillez ouvrir l\'appli."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Appli inconnue"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Arrêter la diffusion"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Fonctionnement des annonces"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Annonce"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Les personnes à proximité équipées d\'appareils Bluetooth compatibles peuvent écouter le contenu multimédia que vous diffusez"</string> diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml index d56e2bad2cc7..46ff121d2fde 100644 --- a/packages/SystemUI/res/values-gl/strings.xml +++ b/packages/SystemUI/res/values-gl/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmada"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toca Confirmar para completar o proceso"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Usouse o desbloqueo facial. Preme a icona de desbloquear."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Usouse o desbloqueo facial. Preme para continuar."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Recoñeceuse a cara. Preme para continuar."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Recoñeceuse a cara. Preme a icona de desbloquear."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autenticado"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Usar PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Usar padrón"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Pasa o dedo cara arriba para abrir"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Preme a icona de desbloquear para abrir a porta"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Usouse o desbloqueo facial. Preme a icona de desbloquear."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Usouse o desbloqueo facial. Preme para abrir."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Recoñeceuse a cara. Preme para abrir."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Recoñeceuse a cara. Preme a icona de desbloquear para abrir."</string> <string name="keyguard_retry" msgid="886802522584053523">"Pasa o dedo cara arriba para tentalo de novo"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloquea o dispositivo para utilizar a NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertence á túa organización."</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Queres continuar coa túa sesión?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Comezar de novo"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Si, continuar"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Modo de convidado"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Estás usando o modo de convidado"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Engadir un usuario novo?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Cando engadas un usuario novo, este deberá configurar o seu espazo.\n\nCalquera usuario pode actualizar as aplicacións para todos os demais usuarios."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Ao engadir un usuario novo, sairás do modo de convidado e eliminaranse todas as aplicacións e datos da sesión de convidado actual."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Alcanzouse o límite de usuarios"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">Podes engadir ata <xliff:g id="COUNT">%d</xliff:g> usuarios.</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Vincular dispositivo novo"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Para emitir esta sesión, abre a aplicación."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Aplicación descoñecida"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Deter emisión"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Como funcionan as difusións?"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Difusión"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"As persoas que estean preto de ti e que dispoñan de dispositivos Bluetooth compatibles poden escoitar o contido multimedia que difundas"</string> diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml index 9981769b1ab4..8a8f9dc43003 100644 --- a/packages/SystemUI/res/values-gu/strings.xml +++ b/packages/SystemUI/res/values-gu/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"પુષ્ટિ કરી"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"પરીક્ષણ પૂર્ણ કરવા કન્ફર્મ કરોને ટૅપ કરો"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"ચહેરા દ્વારા અનલૉક કર્યું. આગળ વધવા \'અનલૉક કરો\' આઇકન દબાવો."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"પ્રમાણિત"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"પિનનો ઉપયોગ કરો"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"પૅટર્નનો ઉપયોગ કરો"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"ખોલવા માટે ઉપરની તરફ સ્વાઇપ કરો"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"ખોલવા માટે \'અનલૉક કરો\' આઇકન દબાવો"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"ચહેરા દ્વારા અનલૉક કર્યું. ખોલવા \'અનલૉક કરો\' આઇકન દબાવો."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"ફરી પ્રયાસ કરવા માટે ઉપરની તરફ સ્વાઇપ કરો"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFCનો ઉપયોગ કરવા માટે અનલૉક કરો"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"આ ડિવાઇસ તમારી સંસ્થાની માલિકીનું છે"</string> @@ -338,6 +350,14 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"શું તમે તમારું સત્ર ચાલુ રાખવા માંગો છો?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"શરૂ કરો"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"હા, ચાલુ રાખો"</string> + <!-- no translation found for guest_notification_app_name (2110425506754205509) --> + <skip /> + <!-- no translation found for guest_notification_session_active (5567273684713471450) --> + <skip /> + <string name="user_add_user_title" msgid="4172327541504825032">"નવા વપરાશકર્તાને ઉમેરીએ?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"જ્યારે તમે કોઈ નવા વપરાશકર્તાને ઉમેરો છો, ત્યારે તે વ્યક્તિને તેમનું સ્થાન સેટ કરવાની જરૂર પડે છે.\n\nકોઈપણ વપરાશકર્તા બધા અન્ય વપરાશકર્તાઓ માટે ઍપને અપડેટ કરી શકે છે."</string> + <!-- no translation found for user_add_user_message_guest_remove (5589286604543355007) --> + <skip /> <string name="user_limit_reached_title" msgid="2429229448830346057">"વપરાશકર્તા સંખ્યાની મર્યાદા"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="one">તમે <xliff:g id="COUNT">%d</xliff:g> વપરાશકર્તા સુધી ઉમેરી શકો છો.</item> @@ -837,7 +857,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"નવા ડિવાઇસ સાથે જોડાણ કરો"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"આ સત્ર કાસ્ટ કરવા માટે, કૃપા કરીને ઍપ ખોલો."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"અજાણી ઍપ"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"કાસ્ટ કરવાનું રોકો"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"બ્રોડકાસ્ટ પ્રક્રિયાની કામ કરવાની રીત"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"બ્રોડકાસ્ટ કરો"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"સુસંગત બ્લૂટૂથ ડિવાઇસ ધરાવતા નજીકના લોકો તમે જે મીડિયા બ્રોડકાસ્ટ કરી રહ્યાં છો તે સાંભળી શકે છે"</string> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index 416e0c400ce0..20af054e072b 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"पुष्टि हो गई"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"\'पुष्टि करें\' पर टैप करके पूरा करें"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"चेहरे से अनलॉक किया. जारी रखने के लिए, अनलॉक आइकॉन को दबाएं."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"पुष्टि हो गई"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"पिन इस्तेमाल करें"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"पैटर्न इस्तेमाल करें"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"खोलने के लिए ऊपर स्वाइप करें"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"डिवाइस अनलॉक करने के लिए, अनलॉक आइकॉन को दबाएं"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"चेहरे से अनलॉक किया. डिवाइस अनलॉक करने के लिए, अनलॉक आइकॉन को दबाएं."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"फिर से कोशिश करने के लिए ऊपर की ओर स्वाइप करें"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"एनएफ़सी इस्तेमाल करने के लिए स्क्रीन को अनलॉक करें"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"इस डिवाइस का मालिकाना हक आपके संगठन के पास है"</string> @@ -338,6 +350,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"क्या आप अपना सत्र जारी रखना चाहते हैं?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"फिर से शुरू करें"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"हां, जारी रखें"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"मेहमान मोड"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"आप मेहमान मोड में हैं"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"नया उपयोगकर्ता जोड़ें?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"जब आप कोई नया उपयोगकर्ता जोड़ते हैं, तो उसे अपनी जगह सेट करनी होती है.\n\nकोई भी उपयोगकर्ता बाकी सभी उपयोगकर्ताओं के लिए ऐप्लिकेशन अपडेट कर सकता है."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"किसी नए उपयोगकर्ता को जोड़ने पर, मेहमान मोड को बंद कर दिया जाएगा. साथ ही, मेहमान के तौर पर ब्राउज़ करने के मौजूदा सेशन से, सभी ऐप्लिकेशन और डेटा को मिटा दिया जाएगा."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"अब और उपयोगकर्ता नहीं जोड़े जा सकते"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="one">आप ज़्यादा से ज़्यादा <xliff:g id="COUNT">%d</xliff:g> उपयोगकर्ता जोड़ सकते हैं.</item> @@ -836,7 +853,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"नया डिवाइस जोड़ें"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"इस सेशन को कास्ट करने के लिए, कृपया ऐप्लिकेशन खोलें."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"अनजान ऐप्लिकेशन"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"कास्टिंग करना रोकें"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ब्रॉडकास्ट करने की सुविधा कैसे काम करती है"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"ब्रॉडकास्ट करें"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"आपके आस-पास मौजूद लोग, ब्रॉडकास्ट किए जा रहे मीडिया को सुन सकते हैं. हालांकि, इसके लिए उनके पास ऐसे ब्लूटूथ डिवाइस होने चाहिए जिन पर मीडिया चलाया जा सके"</string> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index 66613d408711..6d2ed09ae004 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potvrđeno"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Dodirnite Potvrdi za dovršetak"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Otključano pomoću lica. Pritisnite ikonu otključavanja da biste nastavili."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Otključano pomoću lica. Pritisnite da biste nastavili."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Lice je prepoznato. Pritisnite da biste nastavili."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Lice je prepoznato. Pritisnite ikonu otključavanja da biste nastavili."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentičnost provjerena"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Koristite PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Koristite uzorak"</string> @@ -314,6 +317,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Prijeđite prstom prema gore da biste otvorili"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Pritisnite ikonu otključavanja da biste otvorili"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Otključano pomoću lica. Pritisnite ikonu otključavanja da biste otvorili."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Otključano pomoću lica. Pritisnite da biste otvorili."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Lice je prepoznato. Pritisnite da biste otvorili."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Lice je prepoznato. Pritisnite ikonu otključavanja da biste otvorili."</string> <string name="keyguard_retry" msgid="886802522584053523">"Prijeđite prstom prema gore za ponovni pokušaj"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Otključajte da biste upotrijebili NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Ovaj uređaj pripada vašoj organizaciji"</string> @@ -340,6 +346,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Želite li nastaviti sesiju?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Počni ispočetka"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Da, nastavi"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Način rada za goste"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Upotrebljavate način rada za goste"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Dodati novog korisnika?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Kada dodate novog korisnika, ta osoba mora postaviti vlastiti prostor.\n\nBilo koji korisnik može ažurirati aplikacije za sve ostale korisnike."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Ako dodate novog korisnika, napustit ćete način rada za goste i izbrisat će se svi podaci i aplikacije iz trenutačne gostujuće sesije."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Dosegnuto je ograničenje korisnika"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="one">Možete dodati najviše <xliff:g id="COUNT">%d</xliff:g> korisnika.</item> @@ -841,7 +852,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Uparite novi uređaj"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Da biste emitirali ovu sesiju, otvorite aplikaciju."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Nepoznata aplikacija"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Zaustavi emitiranje"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Kako emitiranje funkcionira"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Emitiranje"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Osobe u blizini s kompatibilnim Bluetooth uređajima mogu slušati medije koje emitirate"</string> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index 89693de7b5ff..f39dc2ec62b5 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Megerősítve"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Koppintson a Megerősítés lehetőségre"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Zárolás arccal feloldva. Folytatás: Feloldásra koppintás."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Zárolás arccal feloldva. Koppintson a folytatáshoz."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Arc felismerve. Koppintson a folytatáshoz."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Arc felismerve. A folytatáshoz koppintson a Feloldásra."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Hitelesítve"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN-kód használata"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Minta használata"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Csúsztasson felfelé a megnyitáshoz"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Az eszköz használatához nyomja meg a feloldás ikonját"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Zárolás arccal feloldva. Eszköz használata: Feloldás ikon."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Zárolás arccal feloldva. Koppintson az eszköz használatához."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Arc felismerve. Koppintson az eszköz használatához."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Arc felismerve. Eszköz használata: Feloldás ikon."</string> <string name="keyguard_retry" msgid="886802522584053523">"Az újrapróbálkozáshoz csúsztassa felfelé az ujját"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Az NFC használatához oldja fel a képernyőzárat"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Ez az eszköz az Ön szervezetének tulajdonában van"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Folytatja a munkamenetet?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Újrakezdés"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Igen, folytatom"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Vendég mód"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Vendég módban van"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Új felhasználó hozzáadása?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Ha új felhasználót ad hozzá, az illetőnek be kell állítania saját tárterületét.\n\nBármely felhasználó frissítheti az alkalmazásokat valamennyi felhasználó számára."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Új felhasználó felvételével kilép a vendég módból, és az aktuális vendégmunkamenetből származó összes alkalmazás és adat törlődik majd."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Maximális felhasználószám elérve"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">Legfeljebb <xliff:g id="COUNT">%d</xliff:g> felhasználót adhat hozzá.</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Új eszköz párosítása"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"A munkamenet átküldéséhez nyissa meg az alkalmazást."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Ismeretlen alkalmazás"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Átküldés leállítása"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"A közvetítés működése"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Közvetítés"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"A közelben tartózkodó, kompatibilis Bluetooth-eszközzel rendelkező személyek meghallgathatják az Ön közvetített médiatartalmait"</string> diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml index e21f8e0f044f..c4b159fb0756 100644 --- a/packages/SystemUI/res/values-hy/strings.xml +++ b/packages/SystemUI/res/values-hy/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Հաստատվեց"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Ավարտելու համար հպեք «Հաստատել»"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Ապակողպվել է դեմքով։ Սեղմեք ապակողպման պատկերակը։"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Ապակողպվել է դեմքով։ Սեղմեք շարունակելու համար։"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Դեմքը ճանաչվեց։ Սեղմեք շարունակելու համար։"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Դեմքը ճանաչվեց։ Սեղմեք ապակողպման պատկերակը։"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Նույնականացված է"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Օգտագործել PIN կոդ"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Օգտագործել նախշ"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Բացելու համար սահեցրեք վերև"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Բացեք՝ սեղմելով ապակողպման պատկերակը"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Ապակողպվել է դեմքով։ Բացեք՝ սեղմելով ապակողպման պատկերակը։"</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Ապակողպվել է դեմքով։ Սեղմեք բացելու համար։"</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Դեմքը ճանաչվեց։ Սեղմեք բացելու համար։"</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Դեմքը ճանաչվեց։ Բացելու համար սեղմեք ապակողպման պատկերակը։"</string> <string name="keyguard_retry" msgid="886802522584053523">"Սահեցրեք վերև՝ նորից փորձելու համար"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Ապակողպեք՝ NFC-ն օգտագործելու համար"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Այս սարքը պատկանում է ձեր կազմակերպությանը"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Շարունակե՞լ աշխատաշրջանը։"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Վերսկսել"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Այո, շարունակել"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Հյուրի ռեժիմ"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Դուք հյուրի ռեժիմում եք"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Ավելացնե՞լ նոր օգտատեր"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Երբ նոր օգտատեր եք ավելացնում, նա պետք է կարգավորի իր պրոֆիլը:\n\nՑանկացած օգտատեր կարող է թարմացնել հավելվածները մյուս բոլոր հաշիվների համար:"</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Ավելացնելով նոր օգտատեր՝ դուք դուրս կգաք հյուրի ռեժիմից։ Հյուրի ընթացիկ աշխատաշրջանի բոլոր հավելվածներն ու տվյալները կջնջվեն։"</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Սահմանաչափը սպառված է"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="one">Հնարավոր է ավելացնել առավելագույնը <xliff:g id="COUNT">%d</xliff:g> օգտատեր։</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Նոր սարքի զուգակցում"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Այս աշխատաշրջանը հեռարձակելու համար բացեք հավելվածը"</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Անհայտ հավելված"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Կանգնեցնել հեռարձակումը"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Ինչպես է աշխատում հեռարձակումը"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Հեռարձակում"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Ձեր մոտակայքում գտնվող՝ համատեղելի Bluetooth սարքերով մարդիկ կարող են լսել մեդիա ֆայլերը, որոնք դուք հեռարձակում եք։"</string> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index 3a15692f3e58..219d88a5263c 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Dikonfirmasi"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Ketuk Konfirmasi untuk menyelesaikan"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Kunci dibuka dengan wajah. Tekan ikon buka kunci untuk melanjutkan."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Kunci dibuka dengan wajah. Tekan untuk melanjutkan."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Wajah dikenali. Tekan untuk melanjutkan."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Wajah dikenali. Tekan ikon buka kunci untuk melanjutkan."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Diautentikasi"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Gunakan PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Gunakan pola"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Geser ke atas untuk membuka"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Tekan ikon buka kunci untuk membuka"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Kunci dibuka dengan wajah. Tekan ikon buka kunci untuk membuka."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Kunci dibuka dengan wajah. Tekan untuk membuka."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Wajah dikenali. Tekan untuk membuka."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Wajah dikenali. Tekan ikon buka kunci untuk membuka."</string> <string name="keyguard_retry" msgid="886802522584053523">"Geser ke atas untuk mencoba lagi"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Buka kunci untuk menggunakan NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Perangkat ini milik organisasi Anda"</string> @@ -333,11 +339,16 @@ <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="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengisi Daya dengan Dok • Penuh dalam waktu <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Beralih pengguna"</string> - <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Semua aplikasi dan data di sesi ini akan dihapus."</string> + <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Semua aplikasi dan data dalam sesi ini akan dihapus."</string> <string name="guest_wipe_session_title" msgid="7147965814683990944">"Selamat datang kembali, tamu!"</string> <string name="guest_wipe_session_message" msgid="3393823610257065457">"Lanjutkan sesi Anda?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Mulai ulang"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Ya, lanjutkan"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Mode tamu"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Anda sedang menggunakan mode tamu"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Tambahkan pengguna baru?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Saat Anda menambahkan pengguna baru, orang tersebut perlu menyiapkan ruangnya sendiri.\n\nPengguna mana pun dapat mengupdate aplikasi untuk semua pengguna lain."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Menambahkan pengguna baru akan membuat Anda keluar dari mode tamu dan menghapus semua aplikasi serta data dari sesi tamu saat ini."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Batas pengguna tercapai"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">Anda dapat menambahkan hingga <xliff:g id="COUNT">%d</xliff:g> pengguna.</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Sambungkan perangkat baru"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Buka aplikasi untuk mentransmisikan sesi ini."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Aplikasi tidak dikenal"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Hentikan transmisi"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Cara kerja siaran"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Siaran"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Orang di dekat Anda dengan perangkat Bluetooth yang kompatibel dapat mendengarkan media yang sedang Anda siarkan"</string> diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml index 5ddb0a358735..21645b1224a6 100644 --- a/packages/SystemUI/res/values-is/strings.xml +++ b/packages/SystemUI/res/values-is/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Staðfest"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Ýttu á „Staðfesta“ til að ljúka"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Opnað með andliti. Ýttu á táknið taka úr lás til að halda áfram."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Opnað með andliti. Ýttu til að halda áfram."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Andlitið var greint. Ýttu til að halda áfram."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Andlitið var greint. Ýttu á opnunartáknið til að halda áfr."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Auðkennt"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Nota PIN-númer"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Nota mynstur"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Strjúktu upp til að opna"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Ýttu á táknið til að taka úr lás til að opna"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Opnað með andliti. Ýttu á táknið taka úr lás til að opna."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Opnað með andliti. Ýttu til að opna."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Andlitið var greint. Ýttu til að opna."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Andlitið var greint. Ýttu á opnunartáknið til að opna."</string> <string name="keyguard_retry" msgid="886802522584053523">"Strjúktu upp til að reyna aftur"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Taktu úr lás til að nota NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Þetta tæki tilheyrir fyrirtækinu þínu"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Viltu halda áfram með lotuna?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Byrja upp á nýtt"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Já, halda áfram"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Gestastilling"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Þú ert í gestastillingu"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Bæta nýjum notanda við?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Þegar þú bætir nýjum notanda við þarf sá notandi að setja upp svæðið sitt.\n\nHvaða notandi sem er getur uppfært forrit fyrir alla aðra notendur."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Þegar nýjum notanda er bætt við er gestastillingu lokað og öllum forritum og gögnum úr núverandi gestalotu eytt."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Notandahámarki náð"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="one">Þú getur bætt við allt að <xliff:g id="COUNT">%d</xliff:g> notanda.</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Para nýtt tæki"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Opnaðu forritið til að senda þessa lotu út."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Óþekkt forrit"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Stöðva útsendingu"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Svona virkar útsending"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Útsending"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Fólk nálægt þér með samhæf Bluetooth-tæki getur hlustað á efnið sem þú sendir út"</string> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index 55c854b5d361..6c5026d9f8fe 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confermato"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tocca Conferma per completare"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Sbloccato con il volto. Premi l\'icona Sblocca e continua."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Sbloccato con il volto. Premi per continuare."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Volto riconosciuto. Premi per continuare."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Volto riconosciuto. Premi l\'icona Sblocca e continua."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autenticazione eseguita"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Utilizza PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Usa sequenza"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Scorri verso l\'alto per aprire"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Premi l\'icona Sblocca per aprire"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Sbloccato con il volto. Premi l\'icona Sblocca per aprire."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Sbloccato con il volto. Premi per aprire."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Volto riconosciuto. Premi per aprire."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Volto riconosciuto. Premi l\'icona Sblocca per aprire."</string> <string name="keyguard_retry" msgid="886802522584053523">"Scorri verso l\'alto per riprovare"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Sblocca per usare NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Questo dispositivo appartiene alla tua organizzazione"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Vuoi continuare la sessione?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Ricomincia"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Sì, continua"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Modalità Ospite"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Sei in modalità Ospite"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Aggiungere un nuovo utente?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Il nuovo utente, una volta aggiunto, deve impostare il proprio spazio.\n\nQualsiasi utente può aggiornare le app per tutti gli altri."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Se aggiungi un nuovo utente, la modalità Ospite viene disattivata e vengono eliminati tutti i dati e le app della sessione Ospite corrente."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Limite di utenti raggiunto"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">Puoi aggiungere fino a <xliff:g id="COUNT">%d</xliff:g> utenti.</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Accoppia nuovo dispositivo"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Per trasmettere questa sessione devi aprire l\'app."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"App sconosciuta"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Interrompi trasmissione"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Come funziona la trasmissione"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Annuncio"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Le persone vicine a te che hanno dispositivi Bluetooth compatibili possono ascoltare i contenuti multimediali che stai trasmettendo"</string> diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index 6cbc0a57f535..0049fa07dbf6 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"יש אישור"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"יש להקיש על \'אישור\' לסיום התהליך"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"הנעילה בוטלה בזיהוי פנים. להמשך, לוחצים על סמל ביטול הנעילה."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"מאומת"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"שימוש בקוד אימות"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"שימוש בקו ביטול נעילה"</string> @@ -316,6 +322,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"צריך להחליק כדי לפתוח"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"לפתיחה, לוחצים על סמל ביטול הנעילה"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"הנעילה בוטלה בזיהוי פנים. פותחים בלחיצה על סמל ביטול הנעילה."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"יש להחליק למעלה כדי לנסות שוב"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"יש לבטל את הנעילה כדי להשתמש ב-NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"המכשיר הזה שייך לארגון שלך"</string> @@ -342,6 +354,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"האם ברצונך להמשיך בפעילות באתר?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"סשן חדש"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"כן, להמשיך"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"מצב אורח"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"התחברת במצב אורח"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"להוסיף משתמש חדש?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"כשמוסיפים משתמש חדש, המשתמש הזה צריך להגדיר את השטח שלו.\n\nכל משתמש יכול לעדכן אפליקציות עבור כל המשתמשים האחרים."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"הוספת משתמש חדש תגרום ליציאה ממצב האורח ותמחק את כל האפליקציות והנתונים מהגלישה הנוכחית כאורח."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"הגעת למגבלת המשתמשים שניתן להוסיף"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="two">ניתן להוסיף עד <xliff:g id="COUNT">%d</xliff:g> משתמשים.</item> @@ -848,7 +865,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"התאמה של מכשיר חדש"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"כדי להעביר (cast) את הסשן הזה, צריך לפתוח את האפליקציה."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"אפליקציה לא ידועה"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"עצירת ההעברה (casting)"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"הסבר על שידורים"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"שידור"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"אנשים בקרבת מקום עם מכשירי Bluetooth תואמים יכולים להאזין למדיה שמשודרת על ידך"</string> diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index 4b7e130c5c04..f8374bc917b8 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"確認しました"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"完了するには [確認] をタップしてください"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"顔でロック解除しました。ロック解除アイコンを押して続行します。"</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"認証済み"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN を使用"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"パターンを使用"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"開くには上にスワイプします"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"ロック解除アイコンを押して開きます"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"顔でロック解除しました。ロック解除アイコンを押して開きます。"</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"上にスワイプしてもう一度お試しください"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC を使用するには、ロックを解除してください"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"これは組織が所有するデバイスです"</string> @@ -338,6 +350,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"セッションを続行しますか?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"最初から開始"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"続行"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"ゲストモード"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"ゲストモード使用中"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"新しいユーザーを追加しますか?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"新しいユーザーを追加したら、そのユーザーは自分のスペースをセットアップする必要があります。\n\nすべてのユーザーは他のユーザーに代わってアプリを更新できます。"</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"新しいユーザーを追加するとゲストモードは終了し、現在のゲスト セッションからすべてのアプリとデータが削除されます。"</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"ユーザー数が上限に達しました"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">最大 <xliff:g id="COUNT">%d</xliff:g> 人のユーザーを追加できます。</item> @@ -836,7 +853,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"新しいデバイスとのペア設定"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"このセッションをキャストするには、アプリを開いてください。"</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"不明なアプリ"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"キャストを停止"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ブロードキャストの仕組み"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"ブロードキャスト"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Bluetooth 対応デバイスを持っている付近のユーザーは、あなたがブロードキャストしているメディアを聴けます"</string> diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml index 160927f13492..d044c60cf443 100644 --- a/packages/SystemUI/res/values-ka/strings.xml +++ b/packages/SystemUI/res/values-ka/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"დადასტურებული"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"დასასრულებლად შეეხეთ „დადასტურებას“"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"განიბლოკა სახით. გასაგრძელებლად დააჭირეთ განბლოკვის ხატულას."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"განიბლოკა სახით. დააჭირეთ გასაგრძელებლად."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ამოცნობილია სახით. დააჭირეთ გასაგრძელებლად."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ამოცნობილია სახით. გასაგრძელებლად დააჭირეთ განბლოკვის ხატულას."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"ავტორიზებულია"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN-კოდის გამოყენება"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ნიმუშის გამოყენება"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"გასახსნელად გადაფურცლეთ ზემოთ"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"გასახსნელად დააჭირეთ განბლოკვის ხატულას"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"განიბლოკა სახით. გასახსნელად დააჭირეთ განბლოკვის ხატულას."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"განიბლოკა სახით. დააჭირეთ გასახსნელად."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"ამოცნობილია სახით. დააჭირეთ გასახსნელად."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"ამოცნობილია სახით. გასახსნელად დააჭირეთ განბლოკვის ხატულას."</string> <string name="keyguard_retry" msgid="886802522584053523">"ხელახლა საცდელად გადაფურცლეთ ზემოთ"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"განბლოკეთ NFC-ის გამოსაყენებლად"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ამ მოწყობილობას ფლობს თქვენი ორგანიზაცია"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"გსურთ, თქვენი სესიის გაგრძელება?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"ხელახლა დაწყება"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"დიახ, გავაგრძელოთ"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"სტუმრის რეჟიმი"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"თქვენ სტუმრის რეჟიმში ხართ"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"დაემატოს ახალი მომხმარებელი?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"ახალი მომხმარებლის დამატებისას, ამ მომხმარებელს საკუთარი სივრცის შექმნა მოუწევს.\n\nნებისმიერ მომხმარებელს შეუძლია აპები ყველა სხვა მომხმარებლისათვის განაახლოს."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"თუ ახალ მომხმარებელს დაამატებთ, სტუმრის რეჟიმი დაიხურება და სტუმრის რეჟიმის მიმდინარე სესიიდან ყველა აპი და მონაცემი წაიშლება."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"მიღწეულია მომხმარებელთა ლიმიტი"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">შესაძლებელია <xliff:g id="COUNT">%d</xliff:g>-მდე მომხმარებლის დამატება.</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ახალი მოწყობილობის დაწყვილება"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"ამ სესიის ტრანსლირებისთვის გახსენით აპი."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"უცნობი აპი"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"ტრანსლირების შეწყვეტა"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ტრანსლირების მუშაობის პრინციპი"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"ტრანსლაცია"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"თქვენთან ახლოს მყოფ ხალხს თავსებადი Bluetooth მოწყობილობით შეუძლიათ თქვენ მიერ ტრანსლირებული მედიის მოსმენა"</string> diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml index 6b233c89f536..d2335df6c6b7 100644 --- a/packages/SystemUI/res/values-kk/strings.xml +++ b/packages/SystemUI/res/values-kk/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Расталды"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Аяқтау үшін \"Растау\" түймесін түртіңіз."</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Бет үлгісі арқылы ашылды. Жалғастыру үшін құлыпты ашу белгішесін басыңыз."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Аутентификацияланған"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN кодын пайдалану"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Өрнекті пайдалану"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Ашу үшін жоғары қарай сырғытыңыз."</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Ашу үшін құлыпты ашу белгішесін басыңыз."</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Бет үлгісі арқылы ашылды. Ашу үшін құлыпты ашу белгішесін басыңыз."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"Әрекетті қайталау үшін жоғары сырғытыңыз."</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC пайдалану үшін құлыпты ашыңыз."</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Бұл құрылғы ұйымыңызға тиесілі."</string> @@ -338,6 +350,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Сеансты жалғастыру керек пе?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Қайта бастау"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Иә, жалғастыру"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Қонақ режимі"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Сіз қонақ режиміндесіз"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Жаңа пайдаланушы қосылсын ба?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Жаңа пайдаланушыны қосқанда, сол адам өз кеңістігін реттеуі керек.\n\nКез келген пайдаланушы барлық басқа пайдаланушылар үшін қолданбаларды жаңарта алады."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Жаңа пайдаланушы қосылған кезде, қонақ режимі жабылады, ағымдағы қонақ сеансындағы барлық қолданба мен дерек жойылады."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Пайдаланушылар саны шегіне жетті"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> пайдаланушыға дейін енгізуге болады.</item> @@ -836,7 +853,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Жаңа құрылғымен жұптау"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Бұл сеансты трансляциялау үшін қолданбаны ашыңыз."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Белгісіз қолданба"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Трансляцияны тоқтату"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Тарату қалай жүзеге асады"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Тарату"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Үйлесімді Bluetooth құрылғылары бар маңайдағы адамдар сіз таратып жатқан медиамазмұнды тыңдай алады."</string> diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml index 7dcf066e2891..73a2eae98201 100644 --- a/packages/SystemUI/res/values-km/strings.xml +++ b/packages/SystemUI/res/values-km/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"បានបញ្ជាក់"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ចុច \"បញ្ជាក់\" ដើម្បីបញ្ចប់"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"បានដោះសោដោយប្រើមុខ។ សូមចុចរូបដោះសោ ដើម្បីបន្ត។"</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"បានផ្ទៀងផ្ទាត់"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"ប្រើកូដ PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ប្រើលំនាំ"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"អូសឡើងលើដើម្បីបើក"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"ចុចរូបដោះសោ ដើម្បីបើក"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"បានដោះសោដោយប្រើមុខ។ សូមចុចរូបដោះសោ ដើម្បីបើក។"</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"អូសឡើងលើ ដើម្បីព្យាយាមម្ដងទៀត"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"ដោះសោ ដើម្បីប្រើ NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ឧបករណ៍នេះគឺជាកម្មសិទ្ធិរបស់ស្ថាប័នអ្នក"</string> @@ -338,6 +350,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"តើអ្នកចង់បន្តវគ្គរបស់អ្នកទេ?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"ចាប់ផ្ដើមសាជាថ្មី"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"បាទ/ចាស បន្ត"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"មុខងារភ្ញៀវ"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"អ្នកស្ថិតនៅក្នុងមុខងារភ្ញៀវ"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"បញ្ចូលអ្នកប្រើថ្មីឬ?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"នៅពេលអ្នកបញ្ចូលអ្នកប្រើថ្មី អ្នកប្រើនោះត្រូវរៀបចំកន្លែងរបស់គេ។\n\nអ្នកប្រើណាក៏អាចដំឡើងកំណែកម្មវិធីសម្រាប់អ្នកប្រើទាំងអស់ផ្សេងទៀតបានដែរ។"</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"ការបញ្ចូលអ្នកប្រើប្រាស់ថ្មីនឹងធ្វើឱ្យចាកចេញពីមុខងារភ្ញៀវ និងលុបកម្មវិធីនិងទិន្នន័យទាំងអស់ចេញពីវគ្គភ្ញៀវបច្ចុប្បន្ន។"</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"បានឈានដល់ចំនួនកំណត់អ្នកប្រើប្រាស់"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">អ្នកអាចបញ្ចូលអ្នកប្រើប្រាស់បានរហូតដល់ <xliff:g id="COUNT">%d</xliff:g> នាក់។</item> @@ -836,7 +853,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ផ្គូផ្គងឧបករណ៍ថ្មី"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"ដើម្បីភ្ជាប់វគ្គនេះ សូមបើកកម្មវិធី។"</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"កម្មវិធីដែលមិនស្គាល់"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"បញ្ឈប់ការភ្ជាប់"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"របៀបដែលការផ្សាយដំណើរការ"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"ការផ្សាយ"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"មនុស្សនៅជិតអ្នកដែលមានឧបករណ៍ប៊្លូធូសត្រូវគ្នាអាចស្តាប់មេឌៀដែលអ្នកកំពុងផ្សាយបាន"</string> diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml index f6a38b84d699..f051e30d4b3f 100644 --- a/packages/SystemUI/res/values-kn/strings.xml +++ b/packages/SystemUI/res/values-kn/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ದೃಢೀಕರಿಸಲಾಗಿದೆ"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ಪೂರ್ಣಗೊಳಿಸಲು ದೃಢೀಕರಿಸಿ ಅನ್ನು ಟ್ಯಾಪ್ ಮಾಡಿ"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"ಮುಖವನ್ನು ಬಳಸಿ ಅನ್ಲಾಕ್ ಮಾಡಲಾಗಿದೆ. ಮುಂದುವರಿಯಲು ಅನ್ಲಾಕ್ ಐಕಾನ್ ಅನ್ನು ಒತ್ತಿ."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"ದೃಢೀಕರಿಸಲಾಗಿದೆ"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"ಪಿನ್ ಬಳಸಿ"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ಪ್ಯಾಟರ್ನ್ ಬಳಸಿ"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"ತೆರೆಯಲು ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"ತೆರೆಯಲು ಅನ್ಲಾಕ್ ಐಕಾನ್ ಅನ್ನು ಒತ್ತಿ"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"ಮುಖವನ್ನು ಬಳಸಿ ಅನ್ಲಾಕ್ ಮಾಡಲಾಗಿದೆ. ತೆರೆಯಲು ಅನ್ಲಾಕ್ ಐಕಾನ್ ಅನ್ನು ಒತ್ತಿ."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಲು ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ಬಳಸಲು ಅನ್ಲಾಕ್ ಮಾಡಿ"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ಈ ಸಾಧನವು ನಿಮ್ಮ ಸಂಸ್ಥೆಗೆ ಸೇರಿದೆ"</string> @@ -338,6 +350,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"ನಿಮ್ಮ ಸೆಷನ್ ಮುಂದುವರಿಸಲು ಇಚ್ಚಿಸುವಿರಾ?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"ಪ್ರಾರಂಭಿಸಿ"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"ಹೌದು, ಮುಂದುವರಿಸಿ"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"ಅತಿಥಿ ಮೋಡ್"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"ನೀವು ಅತಿಥಿ ಮೋಡ್ನಲ್ಲಿದ್ದೀರಿ"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"ಹೊಸ ಬಳಕೆದಾರರನ್ನು ಸೇರಿಸುವುದೇ?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"ನೀವು ಒಬ್ಬ ಹೊಸ ಬಳಕೆದಾರರನ್ನು ಸೇರಿಸಿದಾಗ, ಆ ವ್ಯಕ್ತಿಯು ಅವರ ಸ್ಥಳವನ್ನು ಸ್ಥಾಪಿಸಬೇಕಾಗುತ್ತದೆ.\n\nಯಾವುದೇ ಬಳಕೆದಾರರು ಎಲ್ಲಾ ಇತರೆ ಬಳಕೆದಾರರಿಗಾಗಿ ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ಅಪ್ಡೇಟ್ ಮಾಡಬಹುದು."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"ಹೊಸ ಬಳಕೆದಾರರನ್ನು ಸೇರಿಸುವುದರಿಂದ ಅತಿಥಿ ಮೋಡ್ನಿಂದ ನಿರ್ಗಮಿಸುತ್ತದೆ ಮತ್ತು ಪ್ರಸ್ತುತ ಅತಿಥಿ ಸೆಶನ್ನಿಂದ ಎಲ್ಲಾ ಆ್ಯಪ್ಗಳು ಮತ್ತು ಡೇಟಾವನ್ನು ಅಳಿಸುತ್ತದೆ."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"ಬಳಕೆದಾರರ ಮಿತಿ ತಲುಪಿದೆ"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="one">ನೀವು <xliff:g id="COUNT">%d</xliff:g> ಬಳಕೆದಾರರವರೆಗೆ ಸೇರಿಸಬಹುದು.</item> @@ -836,7 +853,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ಹೊಸ ಸಾಧನವನ್ನು ಜೋಡಿಸಿ"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"ಈ ಸೆಶನ್ ಕಾಸ್ಟ್ ಮಾಡಲು, ಆ್ಯಪ್ ಅನ್ನು ತೆರೆಯಿರಿ."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"ಅಪರಿಚಿತ ಆ್ಯಪ್"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"ಬಿತ್ತರಿಸುವುದನ್ನು ನಿಲ್ಲಿಸಿ"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ಪ್ರಸಾರವು ಹೇಗೆ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"ಪ್ರಸಾರ"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"ಹೊಂದಾಣಿಕೆಯಾಗುವ ಬ್ಲೂಟೂತ್ ಸಾಧನಗಳನ್ನು ಹೊಂದಿರುವ ಸಮೀಪದಲ್ಲಿರುವ ಜನರು ನೀವು ಪ್ರಸಾರ ಮಾಡುತ್ತಿರುವ ಮಾಧ್ಯಮವನ್ನು ಆಲಿಸಬಹುದು"</string> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index 1f4f913a5ae2..31935d7e662a 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"확인함"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"완료하려면 확인을 탭하세요."</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"얼굴 인식으로 잠금 해제되었습니다. 계속하려면 잠금 해제 아이콘을 누르세요."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"인증됨"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN 사용"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"패턴 사용"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"위로 스와이프하여 열기"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"기기를 열려면 잠금 해제 아이콘을 누르세요."</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"얼굴 인식으로 잠금 해제되었습니다. 기기를 열려면 잠금 해제 아이콘을 누르세요."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"위로 스와이프하여 다시 시도해 주세요"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"잠금 해제하여 NFC 사용"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"내 조직에 속한 기기입니다."</string> @@ -338,6 +350,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"세션을 계속 진행하시겠습니까?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"다시 시작"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"계속 진행"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"게스트 모드"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"게스트 모드 사용 중"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"신규 사용자를 추가할까요?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"추가된 새로운 사용자는 자신의 공간을 설정해야 합니다.\n\n사용자라면 누구든 다른 사용자를 위해 앱을 업데이트할 수 있습니다."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"새로운 사용자를 추가하면 게스트 모드가 종료되고 기존 게스트 세션의 모든 앱과 데이터가 삭제됩니다."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"사용자 제한 도달"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">사용자를 <xliff:g id="COUNT">%d</xliff:g>명까지 추가할 수 있습니다.</item> @@ -836,7 +853,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"새 기기와 페어링"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"세션을 전송하려면 앱을 열어 주세요"</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"알 수 없는 앱"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"전송 중지"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"브로드캐스팅 작동 원리"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"브로드캐스트"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"호환되는 블루투스 기기를 가진 근처의 사용자가 내가 브로드캐스트 중인 미디어를 수신 대기할 수 있습니다."</string> diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml index 9314c9d0f9f7..cd976c4b0b79 100644 --- a/packages/SystemUI/res/values-ky/strings.xml +++ b/packages/SystemUI/res/values-ky/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Ырасталды"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Бүтүрүү үчүн \"Ырастоо\" баскычын басыңыз"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Кулпусун жүзүңүз менен ачтыңыз. Улантуу үчүн кулпусун ачуу сүрөтчөсүн басыңыз."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Кулпусун жүзүңүз менен ачтыңыз. Улантуу үчүн басыңыз."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Жүз таанылды. Улантуу үчүн басыңыз."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Жүз таанылды. Улантуу үчүн кулпусун ачуу сүрөтчөсүн басыңыз."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Аныктыгы текшерилди"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN кодду колдонуу"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Графикалык ачкычты колдонуу"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Ачуу үчүн өйдө сүрүңүз"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Ачуу үчүн кулпусун ачуу сүрөтчөсүн басыңыз"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Кулпусун жүзүңүз менен ачтыңыз. Ачуу үчүн кулпусун ачуу сүрөтчөсүн басыңыз."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Кулпусун жүзүңүз менен ачтыңыз. Ачуу үчүн басыңыз."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Жүз таанылды. Ачуу үчүн басыңыз."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Жүз таанылды. Ачуу үчүн кулпусун ачуу сүрөтчөсүн басыңыз."</string> <string name="keyguard_retry" msgid="886802522584053523">"Кайталоо үчүн экранды өйдө сүрүңүз"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC колдонуу үчүн түзмөктүн кулпусун ачыңыз"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Бул түзмөк уюмуңузга таандык"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Сеансыңызды улантасызбы?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Кайра баштоо"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Ооба, уланта берели"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Конок режими"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Конок режиминдесиз"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Жаңы колдонуучу кошосузбу?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Жаңы колдонуучу кошулганда, ал өз мейкиндигин түзүп алышы керек.\n\nКолдонмолорду бир колдонуучу жаңыртканда, ал калган бардык колдонуучулар үчүн да жаңырат."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Жаңы колдонуучуну кошсоңуз, конок режими жабылат жана учурдагы конок сеансындагы бардык колдонмолор жана дайындар өчүрүлөт."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Дагы колдонуучу кошууга болбойт"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> колдонуучуга чейин кошууга болот.</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Жаңы түзмөк кошуу"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Бул сеансты тышкы экранга чыгаруу үчүн колдонмону ачыңыз."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Белгисиз колдонмо"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Тышкы экранга чыгарууну токтотуу"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Кабарлоо кантип иштейт"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Кабарлоо"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Шайкеш Bluetooth түзмөктөрү болгон жакын жердеги кишилер кабарлап жаткан медиаңызды уга алышат"</string> diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml index 2a52ab60364e..555e73b01b2b 100644 --- a/packages/SystemUI/res/values-lo/strings.xml +++ b/packages/SystemUI/res/values-lo/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ຢືນຢັນແລ້ວ"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ແຕະຢືນຢັນເພື່ອສຳເລັດ"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"ປົດລັອກດ້ວຍໜ້າແລ້ວ. ກົດໄອຄອນປົດລັອກເພື່ອສືບຕໍ່."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"ປົດລັອກດ້ວຍໜ້າແລ້ວ. ກົດເພື່ອສືບຕໍ່."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ຈຳແນກໜ້າໄດ້ແລ້ວ. ກົດເພື່ອສືບຕໍ່."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ຈຳແນກໜ້າໄດ້ແລ້ວ. ກົດໄອຄອນປົດລັອກເພື່ອສືບຕໍ່."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"ຮັບຮອງຄວາມຖືກຕ້ອງແລ້ວ"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"ໃຊ້ PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ໃຊ້ຮູບແບບ"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"ປັດຂຶ້ນເພື່ອເປີດ"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"ກົດໄອຄອນປົດລັອກເພື່ອເປີດ"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"ປົດລັອກດ້ວຍໜ້າແລ້ວ. ກົດໄອຄອນປົດລັອກເພື່ອເປີດ."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"ປົດລັອກດ້ວຍໜ້າແລ້ວ. ກົດເພື່ອເປີດ."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"ຈຳແນກໜ້າໄດ້ແລ້ວ. ກົດເພື່ອເປີດ."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"ຈຳແນກໜ້າໄດ້ແລ້ວ. ກົດໄອຄອນປົດລັອກເພື່ອເປີດ."</string> <string name="keyguard_retry" msgid="886802522584053523">"ປັດຂຶ້ນເພື່ອລອງໃໝ່"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"ປົດລັອກເພື່ອໃຊ້ NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ອຸປະກອນນີ້ເປັນຂອງອົງການທ່ານ"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"ທ່ານຕ້ອງການສືບຕໍ່ເຊດຊັນຂອງທ່ານບໍ່?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"ເລີ່ມຕົ້ນໃຫມ່"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"ຕົກລົງ, ດຳເນີນການຕໍ່"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"ໂໝດແຂກ"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"ທ່ານກຳລັງຢູ່ໃນໂໝດແຂກ"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"ເພີ່ມຜູ້ໃຊ້ໃໝ່ບໍ?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"ເມື່ອທ່ານເພີ່ມຜູ້ໃຊ້ໃໝ່, ຜູ້ໃຊ້ນັ້ນຈະຕ້ອງຕັ້ງຄ່າພື້ນທີ່ບ່ອນຈັດເກັບຂໍ້ມູນຂອງລາວ.\n\nຜູ້ໃຊ້ທຸກຄົນສາມາດອັບເດດແອັບຂອງຜູ້ໃຊ້ຄົນອື່ນທັງໝົດໄດ້."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"ການເພີ່ມຜູ້ໃຊ້ໃໝ່ຈະອອກຈາກໂໝດແຂກ ແລະ ລຶບແອັບ ແລະ ຂໍ້ມູນທັງໝົດອອກຈາກໄລຍະເວລາຂອງແຂກປັດຈຸບັນ."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"ຮອດຂີດຈຳກັດຜູ້ໃຊ້ແລ້ວ"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">ທ່ານສາມາດເພີ່ມໄດ້ສູງສຸດ <xliff:g id="COUNT">%d</xliff:g> ຄົນ.</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ຈັບຄູ່ອຸປະກອນໃໝ່"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"ເພື່ອສົ່ງສັນຍານເຊດຊັນນີ້, ກະລຸນາເປີດແອັບ."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"ແອັບທີ່ບໍ່ຮູ້ຈັກ"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"ຢຸດການສົ່ງສັນຍານ"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ການອອກອາກາດເຮັດວຽກແນວໃດ"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"ອອກອາກາດ"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"ຄົນທີ່ຢູ່ໃກ້ທ່ານທີ່ມີອຸປະກອນ Bluetooth ທີ່ເຂົ້າກັນໄດ້ຈະສາມາດຟັງມີເດຍທີ່ທ່ານກຳລັງອອກອາກາດຢູ່ໄດ້"</string> diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index 6a7898a2e2fe..df9a2a2d1122 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Patvirtinta"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Paliesk. „Patvirtinti“, kad užbaigtumėte"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Atrakinta pagal veidą. Pasp. atrak. pikt., kad tęstumėte."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentifikuota"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Naudoti PIN kodą"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Naudoti atrakinimo piešinį"</string> @@ -316,6 +322,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Perbraukite aukštyn, kad atidarytumėte"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Paspauskite atrakinimo piktogramą, kad atidarytumėte"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Atrakinta pagal veidą. Pasp. atr. pikt., kad atidarytumėte."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"Jei norite bandyti dar kartą, perbraukite aukštyn"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Norėdami naudoti NFC, atrakinkite"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Šis įrenginys priklauso jūsų organizacijai"</string> @@ -342,6 +354,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Ar norite tęsti sesiją?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Pradėti iš naujo"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Taip, tęsti"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Svečio režimas"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Naudojatės svečio režimu"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Pridėti naują naudotoją?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Kai pridedate naują naudotoją, šis asmuo turi nustatyti savo erdvę.\n\nBet kuris naudotojas gali atnaujinti visų kitų naudotojų programas."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Pridėjus naują naudotoją, bus išeita iš svečio režimo ir iš dabartinės svečio sesijos bus ištrintos visos programos ir duomenys."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Pasiekta naudotojų riba"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="one">Galite pridėti iki <xliff:g id="COUNT">%d</xliff:g> naudotojo.</item> @@ -848,7 +865,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Naujo įrenginio susiejimas"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Jei norite perduoti šį seansą, atidarykite programą."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Nežinoma programa"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Sustabdyti perdavimą"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Kaip veikia transliacija"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Transliacija"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Netoliese esantys žmonės, turintys suderinamus „Bluetooth“ įrenginius, gali klausyti jūsų transliuojamos medijos"</string> diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index b53e763470dc..1828da2ab5b4 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Apstiprināts"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Lai pabeigtu, pieskarieties Apstiprināt"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Atbloķēta ar seju. Turpināt: nospiediet atbloķēšanas ikonu."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentifikācija veikta"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Izmantot PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Izmantot kombināciju"</string> @@ -314,6 +320,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Velciet augšup, lai atvērtu"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Lai atvērtu, nospiediet atbloķēšanas ikonu"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Atbloķēta ar seju. Atvērt: nospiediet atbloķēšanas ikonu."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"Velciet augšup, lai mēģinātu vēlreiz"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Atbloķējiet ierīci, lai izmantotu NFC."</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Šī ierīce pieder jūsu organizācijai."</string> @@ -340,6 +352,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Vai vēlaties turpināt savu sesiju?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Sākt no sākuma"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Jā, turpināt"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Viesa režīms"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Jūs izmantojat viesa režīmu"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Vai pievienot jaunu lietotāju?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Kad pievienosiet jaunu lietotāju, viņam būs jāizveido savs profils.\n\nIkviens lietotājs var atjaunināt lietotnes citu lietotāju vietā."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Ja pievienosiet jaunu lietotāju, viesa režīms tiks aizvērts un visas pašreizējās viesa sesijas lietotnes un dati tiks dzēsti."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Sasniegts lietotāju ierobežojums"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="zero">Varat pievienot ne vairāk kā <xliff:g id="COUNT">%d</xliff:g> lietotājus.</item> @@ -842,7 +859,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Savienošana pārī ar jaunu ierīci"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Lai apraidītu šo sesiju, lūdzu, atveriet lietotni."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Nezināma lietotne"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Apturēt apraidi"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Kā darbojas apraide"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Apraide"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Tuvumā esošās personas ar saderīgām Bluetooth ierīcēm var klausīties jūsu apraidīto multivides saturu."</string> diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml index 2dee0e053d2c..89e8c4ff7ab9 100644 --- a/packages/SystemUI/res/values-mk/strings.xml +++ b/packages/SystemUI/res/values-mk/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Потврдено"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Допрете „Потврди“ за да се заврши"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Отклучено со лице. Притиснете ја иконата за отклучување за да продолжите."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Проверена"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Користи PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Користи шема"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Повлечете за да отворите"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Притиснете ја иконата за отклучување за да отворите"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Отклучено со лице. Притиснете ја иконата за отклучување за да отворите."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"Повлечете нагоре за да се обидете повторно"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Отклучете за да користите NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Уредов е во сопственост на организацијата"</string> @@ -338,6 +350,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Дали сакате да продолжите со сесијата?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Почни одново"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Да, продолжи"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Режим на гостин"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Користите режим на гостин"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Да се додаде нов корисник?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Кога додавате нов корисник, тоа лице треба да го постави својот простор.\n\nСекој корисник може да ажурира апликации за сите други корисници."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Ако додадете нов корисник, ќе излезете од режимот на гостин и ќе ги избришете сите апликации и податоци од тековната гостинска сесија."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Достигнато ограничување на корисник"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="one">Може да додадете најмногу <xliff:g id="COUNT">%d</xliff:g> корисник.</item> @@ -836,7 +853,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Спарете нов уред"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"За да ја емитувате сесијава, отворете ја апликацијата."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Непозната апликација"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Сопри со емитување"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Како функционира емитувањето"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Емитување"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Луѓето во ваша близина со компатибилни уреди со Bluetooth може да ги слушаат аудиозаписите што ги емитувате"</string> diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml index e32e3051e7ea..8b763aac4471 100644 --- a/packages/SystemUI/res/values-ml/strings.xml +++ b/packages/SystemUI/res/values-ml/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"സ്ഥിരീകരിച്ചു"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"പൂർത്തിയാക്കാൻ സ്ഥിരീകരിക്കുക ടാപ്പ് ചെയ്യൂ"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"മുഖം ഉപയോഗിച്ച് അൺലോക്ക് ചെയ്തു. തുടരാൻ അൺലോക്ക് ഐക്കൺ അമർത്തുക."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"മുഖം ഉപയോഗിച്ച് അൺലോക്ക് ചെയ്തു. തുടരാൻ അമർത്തുക."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"മുഖം തിരിച്ചറിഞ്ഞു. തുടരാൻ അമർത്തുക."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"മുഖം തിരിച്ചറിഞ്ഞു. തുടരാൻ അൺലോക്ക് ഐക്കൺ അമർത്തുക."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"പരിശോധിച്ചുറപ്പിച്ചു"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"പിൻ ഉപയോഗിക്കുക"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"പാറ്റേൺ ഉപയോഗിക്കുക"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"തുറക്കാൻ മുകളിലോട്ട് സ്വൈപ്പ് ചെയ്യുക"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"തുറക്കാൻ അൺലോക്ക് ഐക്കൺ അമർത്തുക"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"മുഖം ഉപയോഗിച്ച് അൺലോക്ക് ചെയ്തു. തുറക്കാൻ അൺലോക്ക് ഐക്കൺ അമർത്തുക."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"മുഖം ഉപയോഗിച്ച് അൺലോക്ക് ചെയ്തു. തുറക്കാൻ അമർത്തുക."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"മുഖം തിരിച്ചറിഞ്ഞു. തുറക്കാൻ അമർത്തുക."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"മുഖം തിരിച്ചറിഞ്ഞു. തുറക്കാൻ അൺലോക്ക് ഐക്കൺ അമർത്തുക."</string> <string name="keyguard_retry" msgid="886802522584053523">"വീണ്ടും ശ്രമിക്കാൻ മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്യുക"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ഉപയോഗിക്കാൻ അൺലോക്ക് ചെയ്യുക"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ഈ ഉപകരണം നിങ്ങളുടെ സ്ഥാപനത്തിന്റേതാണ്"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"നിങ്ങളുടെ സെഷൻ തുടരണോ?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"പുനരാംരംഭിക്കുക"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"അതെ, തുടരുക"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"അതിഥി മോഡ്"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"നിങ്ങൾ അതിഥി മോഡിലാണ്"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"പുതിയ ഉപയോക്താവിനെ ചേർക്കണോ?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"നിങ്ങൾ പുതിയൊരു ഉപയോക്താവിനെ ചേർക്കുമ്പോൾ, ആ വ്യക്തിക്ക് അവരുടെ ഇടം സജ്ജീകരിക്കേണ്ടതുണ്ട്.\n\nമറ്റ് എല്ലാ ഉപയോക്താക്കൾക്കുമായി ഏതൊരു ഉപയോക്താവിനും ആപ്പുകൾ അപ്ഡേറ്റ് ചെയ്യാനാവും."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"പുതിയൊരു ഉപയോക്താവിനെ ചേർത്താൽ അതിഥി മോഡിൽ നിന്ന് പുറത്ത് കടക്കുകയും നിലവിലെ അതിഥി മോഡിലുള്ള എല്ലാ ആപ്പുകളും ഡാറ്റയും ഇല്ലാതാക്കുകയും ചെയ്യും."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"ഉപയോക്തൃ പരിധി എത്തി"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">നിങ്ങൾക്ക് <xliff:g id="COUNT">%d</xliff:g> ഉപയോക്താക്കളെ വരെ ചേർക്കാനാവും.</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"പുതിയ ഉപകരണവുമായി ജോടിയാക്കുക"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"ഈ സെഷൻ കാസ്റ്റ് ചെയ്യാൻ, ആപ്പ് തുറക്കുക."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"അജ്ഞാതമായ ആപ്പ്"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"കാസ്റ്റ് ചെയ്യുന്നത് നിർത്തുക"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ബ്രോഡ്കാസ്റ്റ് എങ്ങനെയാണ് പ്രവർത്തിക്കുന്നത്"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"ബ്രോഡ്കാസ്റ്റ്"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"അനുയോജ്യമായ Bluetooth ഉപകരണങ്ങളോടെ സമീപമുള്ള ആളുകൾക്ക് നിങ്ങൾ ബ്രോഡ്കാസ്റ്റ് ചെയ്യുന്ന മീഡിയ കേൾക്കാനാകും"</string> diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml index b953a28fee35..935c3054018a 100644 --- a/packages/SystemUI/res/values-mn/strings.xml +++ b/packages/SystemUI/res/values-mn/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Баталгаажсан"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Дуусгахын тулд баталгаажуулахыг товших"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Царайгаар түгжээг тайлсан. Үргэлжлүүлэхийн тулд түгжээг тайлах дүрс тэмдэг дээр дараарай."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Царайгаар түгжээг тайлсан. Үргэлжлүүлэхийн тулд дарна уу."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Царайг таньсан. Үргэлжлүүлэхийн тулд дарна уу."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Царайг таньсан. Үргэлжлүүлэх бол түгжээг тайлах дүрсийг дар."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Баталгаажуулагдсан"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"ПИН ашиглах"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Хээ ашиглах"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Нээхийн тулд дээш шударна уу"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Нээхийн тулд түгжээг тайлах дүрс тэмдэг дээр дараарай"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Царайгаар түгжээг тайлсан. Нээхийн тулд түгжээг тайлах дүрс тэмдэг дээр дараарай."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Царайгаар түгжээг тайлсан. Нээхийн тулд дарна уу."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Царайг таньсан. Нээхийн тулд дарна уу."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Царайг таньсан. Нээх бол түгжээг тайлах дүрсийг дарна уу."</string> <string name="keyguard_retry" msgid="886802522584053523">"Дахин оролдохын тулд дээш шударна уу"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC-г ашиглахын тулд түгжээг тайлна уу"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Энэ төхөөрөмж танай байгууллагад харьяалагддаг"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Та үргэлжлүүлэхийг хүсэж байна уу?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Дахин эхлүүлэх"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Тийм, үргэлжлүүлэх"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Зочны горим"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Та зочны горимд байна"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Шинэ хэрэглэгч нэмэх үү?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Та шинэ хэрэглэгч нэмбэл тухайн хүн өөрийн профайлыг тохируулах шаардлагатай.\n\nАль ч хэрэглэгч бүх хэрэглэгчийн аппуудыг шинэчлэх боломжтой."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Шинэ хэрэглэгч нэмснээр зочны горимоос гаргах бөгөөд бүх апп болон өгөгдлийг одоогийн зочны харилцан үйлдлээс устгана."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Хэрэглэгчийн хязгаарт хүрсэн"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">Та <xliff:g id="COUNT">%d</xliff:g> хүртэлх хэрэглэгч нэмэх боломжтой.</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Шинэ төхөөрөмж хослуулах"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Энэ үйл явдлыг дамжуулахын тулд аппыг нээнэ үү."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Үл мэдэгдэх апп"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Дамжуулахыг зогсоох"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Нэвтрүүлэлт хэрхэн ажилладаг вэ?"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Нэвтрүүлэлт"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Тохиромжтой Bluetooth төхөөрөмжүүдтэй таны ойролцоох хүмүүс таны нэвтрүүлж буй медиаг сонсох боломжтой"</string> diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml index 4add96d210e8..7177870017b4 100644 --- a/packages/SystemUI/res/values-mr/strings.xml +++ b/packages/SystemUI/res/values-mr/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"निश्चित केले"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"पूर्ण करण्यासाठी खात्री करा वर टॅप करा"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"चेहऱ्याने अनलॉक केले. सुरू ठेवण्यासाठी अनलॉक करा आयकन दाबा."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"ऑथेंटिकेशन केलेले"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"पिन वापरा"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"पॅटर्न वापरा"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"उघडण्यासाठी वर स्वाइप करा"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"उघडण्यासाठी अनलॉक करा आयकन दाबा"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"चेहऱ्याने अनलॉक केले. उघडण्यासाठी अनलॉक करा आयकन दाबा."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"पुन्हा प्रयत्न करण्यासाठी वर स्वाइप करा"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC वापरण्यासाठी स्क्रीन अनलॉक करा"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"हे डिव्हाइस तुमच्या संस्थेचे आहे"</string> @@ -338,6 +350,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"तुम्ही तुमचे सत्र सुरू ठेवू इच्छिता?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"येथून सुरू करा"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"होय, सुरू ठेवा"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"अतिथी मोड"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"तुम्ही अतिथी मोडमध्ये आहात"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"नवीन वापरकर्ता जोडायचा?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"तुम्ही एक नवीन वापरकर्ता जोडता तेव्हा, त्या व्यक्तीने त्यांचे स्थान सेट करणे आवश्यक असते.\n\nकोणताही वापरकर्ता इतर सर्व वापरकर्त्यांसाठी अॅप्स अपडेट करू शकतो."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"नवीन वापरकर्ता जोडल्याने अतिथी मोडमधून बाहेर पडेल आणि सध्याच्या अतिथी सत्रातील सर्व अॅप्स व डेटा हटवला जाईल."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"वापरकर्ता मर्यादा गाठली"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">तुम्ही <xliff:g id="COUNT">%d</xliff:g> वापरकर्त्यांपर्यंत जोडू शकता.</item> @@ -836,7 +853,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"नवीन डिव्हाइससोबत पेअर करा"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"हे सेशन कास्ट करण्यासाठी, कृपया ॲप उघडा."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"अज्ञात अॅप"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"कास्ट करणे थांबवा"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ब्रॉडकास्टिंग कसे काम करते"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"ब्रॉडकास्ट करा"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"कंपॅटिबिल ब्लूटूथ डिव्हाइस असलेले तुमच्या जवळपासचे लोक हे तुम्ही ब्रॉडकास्ट करत असलेला मीडिया ऐकू शकतात"</string> diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index 4b31112a58f4..22411ff0d832 100644 --- a/packages/SystemUI/res/values-ms/strings.xml +++ b/packages/SystemUI/res/values-ms/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Disahkan"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Ketik Sahkan untuk menyelesaikan"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Dibuka kunci dengan wajah. Tekan ikon buka kunci untuk teruskan."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Dibuka kunci dengan wajah. Tekan untuk meneruskan."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Wajah dicam. Tekan untuk meneruskan."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Wajah dicam. Tekan ikon buka kunci untuk meneruskan."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Disahkan"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Gunakan PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Gunakan corak"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Leret ke atas untuk buka"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Tekan ikon buka kunci untuk buka"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Dibuka kunci dengan wajah. Tekan ikon buka kunci untuk buka."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Dibuka kunci dengan wajah. Tekan untuk membuka."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Wajah dicam. Tekan untuk membuka."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Wajah dicam. Tekan ikon buka kunci untuk membuka."</string> <string name="keyguard_retry" msgid="886802522584053523">"Leret ke atas untuk mencuba lagi"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Buka kunci untuk menggunakan NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Peranti ini milik organisasi anda"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Adakah anda ingin meneruskan sesi anda?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Mulakan semula"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Ya, teruskan"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Mod tetamu"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Anda dalam mod tetamu"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Tambah pengguna baharu?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Apabila anda menambah pengguna baharu, orang itu perlu menyediakan ruang mereka.\n\nMana-mana pengguna boleh mengemas kini apl untuk semua pengguna lain."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Tindakan menambahkan pengguna baharu akan menyebabkan anda keluar daripada mod tetamu dan memadamkan semua apl dan data daripada sesi tetamu semasa."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Had pengguna dicapai"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">Anda boleh menambah sehingga <xliff:g id="COUNT">%d</xliff:g> pengguna.</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Gandingkan peranti baharu"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Untuk menghantar sesi ini, sila buka apl."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Apl yang tidak diketahui"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Berhenti menghantar"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Cara siaran berfungsi"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Siarkan"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Orang berdekatan anda dengan peranti Bluetooth yang serasi boleh mendengar media yang sedang anda siarkan"</string> diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml index 6f9250cc2c36..0d20d0f9879c 100644 --- a/packages/SystemUI/res/values-my/strings.xml +++ b/packages/SystemUI/res/values-my/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"အတည်ပြုပြီးပြီ"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"အပြီးသတ်ရန်အတွက် \'အတည်ပြုရန်\' ကို တို့ပါ"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"မျက်နှာဖြင့် ဖွင့်ထားသည်။ ရှေ့ဆက်ရန် လော့ခ်ဖွင့်သင်္ကေတကို နှိပ်ပါ။"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"မျက်နှာဖြင့် ဖွင့်ထားသည်။ ရှေ့ဆက်ရန် နှိပ်ပါ။"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"မျက်နှာ မှတ်မိသည်။ ရှေ့ဆက်ရန် နှိပ်ပါ။"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"မျက်နှာ မှတ်မိသည်။ ရှေ့ဆက်ရန် လော့ခ်ဖွင့်သင်္ကေတကို နှိပ်ပါ။"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"အထောက်အထားစိစစ်ပြီးပြီ"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"ပင်နံပါတ်သုံးရန်"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ပုံစံကို သုံးရန်"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"ဖွင့်ရန် အပေါ်သို့ပွတ်ဆွဲပါ"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"ဖွင့်ရန် လော့ခ်ဖွင့်သင်္ကေတကို နှိပ်ပါ"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"မျက်နှာဖြင့် ဖွင့်ထားသည်။ ဖွင့်ရန် လော့ခ်ဖွင့်သင်္ကေတကို နှိပ်ပါ။"</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"မျက်နှာဖြင့် ဖွင့်ထားသည်။ ဖွင့်ရန် နှိပ်ပါ။"</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"မျက်နှာ မှတ်မိသည်။ ဖွင့်ရန် နှိပ်ပါ။"</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"မျက်နှာ မှတ်မိသည်။ ဖွင့်ရန် လော့ခ်ဖွင့်သင်္ကေတကို နှိပ်ပါ။"</string> <string name="keyguard_retry" msgid="886802522584053523">"ထပ်စမ်းကြည့်ရန် အပေါ်သို့ပွတ်ဆွဲပါ"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ကို အသုံးပြုရန် လော့ခ်ဖွင့်ပါ"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ဤစက်ကို သင့်အဖွဲ့အစည်းက ပိုင်ဆိုင်သည်"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"သင်၏ စက်ရှင်ကို ဆက်လုပ်လိုပါသလား။"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"ပြန်စပါ"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"ဆက်လုပ်ပါ"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"ဧည့်သည်မုဒ်"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"သင်သည် ဧည့်သည်မုဒ်တွင် ဖြစ်သည်"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"အသုံးပြုသူအသစ်ကို ထည့်မလား။"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"သင်ထည့်လိုက်သော အသုံးပြုသူအသစ်သည် ၎င်း၏နေရာကို သတ်မှတ်စီစဉ်ရန် လိုအပ်သည်။\n\nမည်သည့်အသုံးပြုသူမဆို ကျန်သူများအားလုံးအတွက် အက်ပ်များကို အပ်ဒိတ်လုပ်ပေးနိုင်သည်။"</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"အသုံးပြုသူ အသစ်ထည့်ခြင်းက ဧည့်သည်မုဒ်မှ ထွက်သွားမည်ဖြစ်ပြီး လက်ရှိဧည့်သည် စက်ရှင်မှ အက်ပ်နှင့် ဒေတာအားလုံးကို ဖျက်လိုက်ပါမည်။"</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"အသုံးပြုသူ အကန့်အသတ် ပြည့်သွားပါပြီ"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">အသုံးပြုသူ <xliff:g id="COUNT">%d</xliff:g> ဦးအထိ ထည့်နိုင်သည်။</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"စက်အသစ် တွဲချိတ်ရန်"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"အက်ပ်ဖွင့်ပြီး ဤစက်ရှင်ကို ကာစ်လုပ်နိုင်သည်။"</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"အမည်မသိ အက်ပ်"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"ကာစ် ရပ်ရန်"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ထုတ်လွှင့်မှုဆောင်ရွက်ပုံ"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"ထုတ်လွှင့်ခြင်း"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"အနီးရှိတွဲသုံးနိုင်သော ဘလူးတုသ်သုံးစက် အသုံးပြုသူများက သင်ထုတ်လွှင့်နေသော မီဒီယာကို နားဆင်နိုင်သည်"</string> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index c946ca58c262..857f3a2a477a 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bekreftet"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Trykk på Bekreft for å fullføre"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Låst opp med ansiktet. Trykk på lås opp-ikon for å fortsette"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Låst opp med ansiktet. Trykk for å fortsette."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Ansiktet er gjenkjent. Trykk for å fortsette."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Ansiktet er gjenkjent. Trykk på lås opp-ikon for å fortsette"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentisert"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Bruk PIN-kode"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Bruk mønster"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Sveip opp for å åpne"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Trykk på lås opp-ikonet for å åpne"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Låst opp med ansiktet. Trykk på lås opp-ikon for å fortsette"</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Låst opp med ansiktet. Trykk for å åpne."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Ansiktet er gjenkjent. Trykk for å åpne."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Ansiktet er gjenkjent. Trykk på lås opp-ikon for å fortsette"</string> <string name="keyguard_retry" msgid="886802522584053523">"Sveip opp for å prøve igjen"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Lås opp for å bruke NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Denne enheten tilhører organisasjonen din"</string> @@ -333,11 +339,16 @@ <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="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ladedokk • Fulladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Bytt bruker"</string> - <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle appene og all informasjon i denne økten slettes."</string> + <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle apper og data i denne økten blir slettet."</string> <string name="guest_wipe_session_title" msgid="7147965814683990944">"Velkommen tilbake, gjest!"</string> <string name="guest_wipe_session_message" msgid="3393823610257065457">"Vil du fortsette økten?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Start på nytt"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Ja, fortsett"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Gjestemodus"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Du er i gjestemodus"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Vil du legge til en ny bruker?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Når du legger til en ny bruker, må vedkommende konfigurere sitt eget område.\n\nAlle brukere kan oppdatere apper for alle andre brukere."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Hvis du legger til en ny bruker, avsluttes gjestemodus, og alle apper og data fra den gjeldende gjesteøkten slettes."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Grensen for antall brukere er nådd"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">Du kan legge til opptil <xliff:g id="COUNT">%d</xliff:g> brukere.</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Koble til en ny enhet"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"For å caste denne økten, åpne appen."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Ukjent app"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Stopp castingen"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Slik fungerer kringkasting"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Kringkasting"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Folk i nærheten med kompatible Bluetooth-enheter kan lytte til mediene du kringkaster"</string> diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml index d285c76e49f8..ab93cbd92d5e 100644 --- a/packages/SystemUI/res/values-ne/strings.xml +++ b/packages/SystemUI/res/values-ne/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"पुष्टि भयो"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"पूरा गर्नका लागि पुष्टि गर्नुहोस् नामक विकल्पमा ट्याप गर्नुहोस्"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"अनुहार प्रयोग गरी अनलक गरियो। जारी राख्न अनलक आइकनमा थिच्नुहोस्।"</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"प्रमाणीकरण गरियो"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN प्रयोग गर्नुहोस्"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ढाँचा प्रयोग गर्नुहोस्"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"खोल्न माथितिर स्वाइप गर्नुहोस्"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"खोल्न अनलक आइकनमा थिच्नुहोस्"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"अनुहार प्रयोग गरी अनलक गरियो। खोल्न अनलक आइकनमा थिच्नुहोस्।"</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"फेरि प्रयास गर्न माथितिर स्वाइप गर्नुहोस्"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC प्रयोग गर्न स्क्रिन अनलक गर्नुहोस्"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"यो डिभाइस तपाईंको सङ्गठनको स्वामित्वमा छ"</string> @@ -338,6 +350,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"तपाईं आफ्नो सत्र जारी गर्न चाहनुहुन्छ?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"सुरु गर्नुहोस्"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"हो, जारी राख्नुहोस्"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"अतिथि मोड"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"तपाईं अतिथि मोड चलाउँदै हुनुहुन्छ"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"नयाँ प्रयोगकर्ता थप्ने हो?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"जब तपाईँले नयाँ प्रयोगकर्ता थप्नुहुन्छ, त्यस प्रयोगकर्ताले आफ्नो स्थान स्थापना गर्न पर्ने छ।\n\nसबै प्रयोगकर्ताले अरू प्रयोगकर्ताका एपहरू अपडेट गर्न सक्छन्।"</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"तपाईंले नयाँ प्रयोगकर्ता थप्नुभयो भने तपाईं अतिथि मोडबाट बाहिरिनु हुने छ र हालको अतिथि सत्रका सबै एप तथा डेटा मेटिने छ।"</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"प्रयोगकर्ताको सीमा पुग्यो"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">तपाईं अधिकतम <xliff:g id="COUNT">%d</xliff:g> प्रयोगहरू मात्र थप्न सक्नुहुन्छ।</item> @@ -836,7 +853,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"नयाँ डिभाइस कनेक्ट गर्नुहोस्"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"यो सत्र कास्ट गर्न चाहनुहुन्छ भने कृपया एप खोल्नुहोस्।"</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"अज्ञात एप"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"कास्ट गर्न छाड्नुहोस्"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"प्रसारण गर्ने सुविधाले कसरी काम गर्छ"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"प्रसारण"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"कम्प्याटिबल ब्लुटुथ डिभाइस भएका नजिकैका मान्छेहरू तपाईंले प्रसारण गरिरहनुभएको मिडिया सुन्न सक्छन्"</string> diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml index dc2bee56373c..54c5490d9fe6 100644 --- a/packages/SystemUI/res/values-night/colors.xml +++ b/packages/SystemUI/res/values-night/colors.xml @@ -66,12 +66,10 @@ <!-- media output dialog--> <color name="media_dialog_background">@color/material_dynamic_neutral10</color> - <color name="media_dialog_item_main_content">@color/material_dynamic_primary90</color> - <color name="media_dialog_item_background">@color/material_dynamic_neutral_variant20</color> - <color name="media_dialog_connected_item_background">@color/material_dynamic_secondary20</color> - <color name="media_dialog_seekbar_progress">@color/material_dynamic_secondary40</color> - <color name="media_dialog_button_background">@color/material_dynamic_primary70</color> - <color name="media_dialog_solid_button_text">@color/material_dynamic_secondary20</color> + <color name="media_dialog_active_item_main_content">@color/material_dynamic_neutral10</color> + <color name="media_dialog_inactive_item_main_content">@color/material_dynamic_neutral10</color> + <color name="media_dialog_item_status">@color/material_dynamic_neutral10</color> + <color name="media_dialog_item_background">@color/material_dynamic_secondary95</color> <!-- Biometric dialog colors --> <color name="biometric_dialog_gray">#ffcccccc</color> diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index af703fda6c78..dbbdec23b123 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bevestigd"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tik op Bevestigen om te voltooien"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Ontgrendeld via gezicht. Druk op het ontgrendelicoon."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Ontgrendeld via gezicht. Druk om door te gaan."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Gezicht herkend. Druk om door te gaan."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Gezicht herkend. Druk op het ontgrendelicoon."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Geverifieerd"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Pincode gebruiken"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Patroon gebruiken"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Swipe omhoog om te openen"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Druk op het ontgrendelicoon om te openen"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Ontgrendeld via gezicht. Druk op het ontgrendelicoon."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Ontgrendeld via gezicht. Druk om te openen."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Gezicht herkend. Druk om te openen."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Gezicht herkend. Druk op het ontgrendelicoon."</string> <string name="keyguard_retry" msgid="886802522584053523">"Swipe omhoog om het opnieuw te proberen"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Ontgrendel het apparaat om NFC te gebruiken"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Dit apparaat is eigendom van je organisatie"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Wil je doorgaan met je sessie?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Opnieuw starten"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Ja, doorgaan"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Gastmodus"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Je gebruikt de gastmodus"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Nieuwe gebruiker toevoegen?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Als je een nieuwe gebruiker toevoegt, moet die persoon zijn eigen profiel instellen.\n\nElke gebruiker kan apps updaten voor alle andere gebruikers."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Als je een nieuwe gebruiker toevoegt, wordt de gastmodus afgesloten en worden alle apps en gegevens van de huidige gastsessie verwijderd."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Gebruikerslimiet bereikt"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">Je kunt maximaal <xliff:g id="COUNT">%d</xliff:g> gebruikers toevoegen.</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Nieuw apparaat koppelen"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Als je deze sessie wilt casten, open je de app."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Onbekende app"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Casten stoppen"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Hoe uitzenden werkt"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Uitzending"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Mensen bij jou in de buurt met geschikte bluetooth-apparaten kunnen luisteren naar de media die je uitzendt"</string> diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml index 61be8439ccf7..d8536653f9f4 100644 --- a/packages/SystemUI/res/values-or/strings.xml +++ b/packages/SystemUI/res/values-or/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ସୁନିଶ୍ଚିତ କରାଯାଇଛି"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ସମ୍ପୂର୍ଣ୍ଣ କରିବାକୁ ସୁନିଶ୍ଚିତ କରନ୍ତୁରେ ଟାପ୍ କରନ୍ତୁ"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"ଫେସ ମାଧ୍ୟମରେ ଅନଲକ କରାଯାଇଛି। ଜାରି ରଖିବାକୁ ଅନଲକ ଆଇକନ ଦବାନ୍ତୁ।"</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"ପ୍ରାମାଣିକତା ହୋଇଛି"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN ବ୍ୟବହାର କରନ୍ତୁ"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ପାଟର୍ନ ବ୍ୟବହାର କରନ୍ତୁ"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"ଖୋଲିବା ପାଇଁ ଉପରକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"ଖୋଲିବାକୁ ଅନଲକ ଆଇକନ ଦବାନ୍ତୁ"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"ଫେସ ମାଧ୍ୟମରେ ଅନଲକ କରାଯାଇଛି। ଖୋଲିବାକୁ ଅନଲକ ଆଇକନ ଦବାନ୍ତୁ।"</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"ପୁଣି ଚେଷ୍ଟା କରିବା ପାଇଁ ଉପରକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ବ୍ୟବହାର କରିବାକୁ ଅନଲକ୍ କରନ୍ତୁ"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ଏହି ଡିଭାଇସଟି ଆପଣଙ୍କ ସଂସ୍ଥାର ଅଟେ"</string> @@ -338,6 +350,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"ଆପଣ ନିଜର ସେସନ୍ ଜାରି ରଖିବାକୁ ଚାହାଁନ୍ତି କି?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"ଆରମ୍ଭ କରନ୍ତୁ"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"ହଁ, ଜାରି ରଖନ୍ତୁ"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"ଅତିଥି ମୋଡ"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"ଆପଣ ଅତିଥି ମୋଡରେ ଅଛନ୍ତି"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"ନୂତନ ଉପଯୋଗକର୍ତ୍ତା ଯୋଗ କରିବେ?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"ଆପଣ ଜଣେ ନୂଆ ଉପଯୋଗକର୍ତ୍ତାଙ୍କୁ ଯୋଗ କଲେ,ତାଙ୍କୁ ସ୍ପେସ୍ ସେଟ୍ ଅପ୍ କରିବାକୁ ପଡ଼ିବ। \n \n ଅନ୍ୟ ସମସ୍ତ ଉପଯୋଗକର୍ତ୍ତାଙ୍କ ପାଇଁ ଯେ କୌଣସି ଉପଯୋଗକର୍ତ୍ତା ଆପଗୁଡ଼ିକୁ ଅପଡେଟ୍ କରିପାରିବେ।"</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"ଜଣେ ନୂଆ ଉପଯୋଗକର୍ତ୍ତାଙ୍କୁ ଯୋଗ କରିବା ଦ୍ୱାରା ଅତିଥି ମୋଡରୁ ବାହାରି ଯିବ ଏବଂ ବର୍ତ୍ତମାନର ଅତିଥି ସେସନରୁ ସମସ୍ତ ଆପ ଓ ଡାଟା ଡିଲିଟ ହୋଇଯିବ।"</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"ଉପଯୋଗକର୍ତ୍ତା ସୀମାରେ ପହଞ୍ଚିଛି"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">କେବଳ <xliff:g id="COUNT">%d</xliff:g> ଉପଯୋଗକର୍ତ୍ତା ହିଁ ତିଆରି କରିହେବ।</item> @@ -836,7 +853,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ନୂଆ ଡିଭାଇସକୁ ପେୟାର୍ କରନ୍ତୁ"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"ଏହି ସେସନକୁ କାଷ୍ଟ କରିବା ପାଇଁ, ଦୟାକରି ଆପ ଖୋଲନ୍ତୁ।"</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"ଅଜଣା ଆପ"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"କାଷ୍ଟ କରିବା ବନ୍ଦ କରନ୍ତୁ"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ବ୍ରଡକାଷ୍ଟିଂ କିପରି କାମ କରେ"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"ବ୍ରଡକାଷ୍ଟ"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"ଆପଣଙ୍କ ଆଖପାଖର କମ୍ପାଟିବଲ ବ୍ଲୁଟୁଥ ଡିଭାଇସ ଥିବା ଲୋକମାନେ ଆପଣ ବ୍ରଡକାଷ୍ଟ କରୁଥିବା ମିଡିଆ ଶୁଣିପାରିବେ"</string> diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml index e03dbf34fd96..1d26f1253227 100644 --- a/packages/SystemUI/res/values-pa/strings.xml +++ b/packages/SystemUI/res/values-pa/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ਪੁਸ਼ਟੀ ਕੀਤੀ ਗਈ"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ਪੂਰਾ ਕਰਨ ਲਈ ਪੁਸ਼ਟੀ ਕਰੋ \'ਤੇ ਟੈਪ ਕਰੋ"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"ਚਿਹਰੇ ਰਾਹੀਂ ਅਣਲਾਕ ਕੀਤਾ ਗਿਆ। ਜਾਰੀ ਰੱਖਣ ਲਈ \'ਅਣਲਾਕ ਕਰੋ\' ਪ੍ਰਤੀਕ ਨੂੰ ਦਬਾਓ।"</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"ਪ੍ਰਮਾਣਿਤ ਹੋਇਆ"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"ਪਿੰਨ ਵਰਤੋ"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ਪੈਟਰਨ ਵਰਤੋ"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"ਖੋਲ੍ਹਣ ਲਈ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"ਖੋਲ੍ਹਣ ਲਈ \'ਅਣਲਾਕ ਕਰੋ\' ਪ੍ਰਤੀਕ ਨੂੰ ਦਬਾਓ"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"ਚਿਹਰੇ ਰਾਹੀਂ ਅਣਲਾਕ ਕੀਤਾ ਗਿਆ। ਖੋਲ੍ਹਣ ਲਈ \'ਅਣਲਾਕ ਕਰੋ\' ਪ੍ਰਤੀਕ ਨੂੰ ਦਬਾਓ।"</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰਨ ਲਈ ਉੱਤੇ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ਵਰਤਣ ਲਈ ਅਣਲਾਕ ਕਰੋ"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ਇਹ ਡੀਵਾਈਸ ਤੁਹਾਡੀ ਸੰਸਥਾ ਨਾਲ ਸੰਬੰਧਿਤ ਹੈ"</string> @@ -338,6 +350,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"ਕੀ ਤੁਸੀਂ ਆਪਣਾ ਸੈਸ਼ਨ ਜਾਰੀ ਰੱਖਣਾ ਚਾਹੁੰਦੇ ਹੋ?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"ਮੁੜ-ਸ਼ੁਰੂ ਕਰੋ"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"ਹਾਂ, ਜਾਰੀ ਰੱਖੋ"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"ਮਹਿਮਾਨ ਮੋਡ"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"ਤੁਸੀਂ ਮਹਿਮਾਨ ਮੋਡ ਵਿੱਚ ਹੋ"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"ਕੀ ਨਵਾਂ ਵਰਤੋਂਕਾਰ ਸ਼ਾਮਲ ਕਰਨਾ ਹੈ?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"ਜਦੋਂ ਤੁਸੀਂ ਇੱਕ ਨਵਾਂ ਵਰਤੋਂਕਾਰ ਸ਼ਾਮਲ ਕਰਦੇ ਹੋ, ਉਸ ਵਿਅਕਤੀ ਨੂੰ ਆਪਣੀ ਜਗ੍ਹਾ ਸਥਾਪਤ ਕਰਨ ਦੀ ਲੋੜ ਹੁੰਦੀ ਹੈ।\n\nਕੋਈ ਵੀ ਵਰਤੋਂਕਾਰ ਹੋਰ ਸਾਰੇ ਵਰਤੋਂਕਾਰਾਂ ਦੀਆਂ ਐਪਾਂ ਨੂੰ ਅੱਪਡੇਟ ਕਰ ਸਕਦਾ ਹੈ।"</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"ਨਵੇਂ ਵਰਤੋਂਕਾਰ ਨੂੰ ਸ਼ਾਮਲ ਕਰਨ ਨਾਲ ਮੌਜੂਦਾ ਮਹਿਮਾਨ ਮੋਡ ਚਲਾ ਜਾਵੇਗਾ ਅਤੇ ਮੌਜੂਦਾ ਮਹਿਮਾਨ ਸੈਸ਼ਨ ਦੀਆਂ ਸਾਰੀਆਂ ਐਪਾਂ ਅਤੇ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"ਵਰਤੋਂਕਾਰ ਸ਼ਾਮਲ ਕਰਨ ਦੀ ਸੀਮਾ ਪੂਰੀ ਹੋਈ"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="one">ਤੁਸੀਂ <xliff:g id="COUNT">%d</xliff:g> ਤੱਕ ਵਰਤੋਂਕਾਰ ਸ਼ਾਮਲ ਕਰ ਸਕਦੇ ਹੋ।</item> @@ -836,7 +853,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ਨਵਾਂ ਡੀਵਾਈਸ ਜੋੜਾਬੱਧ ਕਰੋ"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"ਇਸ ਸੈਸ਼ਨ ਨੂੰ ਕਾਸਟ ਕਰਨ ਲਈ, ਕਿਰਪਾ ਕਰਕੇ ਐਪ ਖੋਲ੍ਹੋ।"</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"ਅਗਿਆਤ ਐਪ"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"ਕਾਸਟ ਕਰਨਾ ਬੰਦ ਕਰੋ"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ਪ੍ਰਸਾਰਨ ਕਿਵੇਂ ਕੰਮ ਕਰਦਾ ਹੈ"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"ਪ੍ਰਸਾਰਨ"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"ਅਨੁਰੂਪ ਬਲੂਟੁੱਥ ਡੀਵਾਈਸਾਂ ਨਾਲ ਨਜ਼ਦੀਕੀ ਲੋਕ ਤੁਹਾਡੇ ਵੱਲੋਂ ਪ੍ਰਸਾਰਨ ਕੀਤੇ ਜਾ ਰਹੇ ਮੀਡੀਆ ਨੂੰ ਸੁਣ ਸਕਦੇ ਹਨ"</string> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index 0ebbb4999c1b..382257918b06 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potwierdzono"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Aby zakończyć, kliknij Potwierdź"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Odblokowano skanem twarzy. Aby kontynuować, kliknij ikonę odblokowywania."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Uwierzytelniono"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Użyj kodu PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Użyj wzoru"</string> @@ -316,6 +322,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Przesuń w górę, by otworzyć"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Aby otworzyć, kliknij ikonę odblokowywania"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Odblokowano skanem twarzy. Aby otworzyć, kliknij ikonę odblokowywania."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"Przesuń w górę, by spróbować ponownie"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Odblokuj, by użyć komunikacji NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"To urządzenie należy do Twojej organizacji"</string> @@ -342,6 +354,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Chcesz kontynuować sesję?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Rozpocznij nową"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Tak, kontynuuj"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Tryb gościa"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Jesteś w trybie gościa"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Dodać nowego użytkownika?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Gdy dodasz nowego użytkownika, musi on skonfigurować swój profil.\n\nKażdy użytkownik może aktualizować aplikacje wszystkich innych użytkowników."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Dodanie nowego użytkownika spowoduje zamknięcie trybu gościa. Wszystkie aplikacje i dane z obecnej sesji gościa zostaną usunięte."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Osiągnięto limit użytkowników"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="few">Możesz dodać maksymalnie <xliff:g id="COUNT">%d</xliff:g> użytkowników.</item> @@ -848,7 +865,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Sparuj nowe urządzenie"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Aby przesłać tę sesję, otwórz aplikację."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Nieznana aplikacja"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Zatrzymaj przesyłanie"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Jak działa transmitowanie"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Transmisja"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Osoby w pobliżu ze zgodnymi urządzeniami Bluetooth mogą słuchać transmitowanych przez Ciebie multimediów"</string> diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml index 8ae76bc6381d..58a6a680a088 100644 --- a/packages/SystemUI/res/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res/values-pt-rBR/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmada"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toque em \"Confirmar\" para concluir"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Desbloqueado pelo rosto. Pressione o ícone de desbloqueio para continuar."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Desbloqueado pelo rosto. Pressione para continuar."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Rosto reconhecido. Pressione para continuar."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Rosto reconhecido. Pressione o ícone para continuar."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autenticado"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Usar PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Usar padrão"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Deslize para cima para abrir"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Pressione o ícone de desbloqueio para abrir"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Desbloqueado pelo rosto. Pressione o ícone de desbloqueio para abrir."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Desbloqueado pelo rosto. Pressione para abrir."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Rosto reconhecido. Pressione para abrir."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Rosto reconhecido. Pressione o ícone de desbloq. para abrir."</string> <string name="keyguard_retry" msgid="886802522584053523">"Deslize para cima para tentar novamente"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloqueie para usar a NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertence à sua organização"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Quer continuar a sessão?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Recomeçar"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Sim, continuar"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Modo visitante"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Você está no modo visitante"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Adicionar novo usuário?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Quando você adiciona um novo usuário, essa pessoa precisa configurar o próprio espaço.\n\nQualquer usuário pode atualizar apps para os demais usuários."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Ao adicionar um novo usuário, o dispositivo vai sair do modo visitante e excluir todos os apps e dados da Sessão de visitante atual."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Limite de usuários atingido"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="one">É possível adicionar até <xliff:g id="COUNT">%d</xliff:g> usuário.</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Parear novo dispositivo"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Abra o app para transmitir esta sessão."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"App desconhecido"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Parar transmissão"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Como funciona a transmissão"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Transmitir"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"As pessoas próximas a você com dispositivos Bluetooth compatíveis podem ouvir a mídia que você está transmitindo"</string> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index f9c4bee31359..4d910346a5ae 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmado"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toque em Confirmar para concluir."</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Desbloqueado c/ rosto. Prima o ícone de desb. p/ continuar."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autenticado"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Utilizar PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Utilizar padrão"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Deslize rapidamente para cima para abrir"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Prima o ícone de desbloqueio para abrir"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Desbloqueado com o rosto. Prima o ícone de desbl. p/ abrir."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"Deslize rapidamente para cima para tentar novamente."</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloquear para utilizar o NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertence à sua entidade."</string> @@ -338,6 +350,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Pretende continuar a sessão?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Recomeçar"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Sim, continuar"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Modo convidado"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Está no modo convidado"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Adicionar um novo utilizador?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Ao adicionar um novo utilizador, essa pessoa tem de configurar o respetivo espaço.\n\nQualquer utilizador pode atualizar apps para todos os outros utilizadores."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Ao adicionar um novo utilizador, o modo convidado é fechado e todas as apps e dados da sessão de convidado atual são eliminados."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Limite de utilizadores alcançado"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">Pode adicionar até <xliff:g id="COUNT">%d</xliff:g> utilizadores.</item> @@ -836,7 +853,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Sincronize o novo dispositivo"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Para transmitir esta sessão, abra a app."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"App desconhecida"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Parar transmissão"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Como funciona a transmissão"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Transmissão"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"As pessoas próximas de si com dispositivos Bluetooth compatíveis podem ouvir o conteúdo multimédia que está a transmitir"</string> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index 8ae76bc6381d..58a6a680a088 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmada"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toque em \"Confirmar\" para concluir"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Desbloqueado pelo rosto. Pressione o ícone de desbloqueio para continuar."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Desbloqueado pelo rosto. Pressione para continuar."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Rosto reconhecido. Pressione para continuar."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Rosto reconhecido. Pressione o ícone para continuar."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autenticado"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Usar PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Usar padrão"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Deslize para cima para abrir"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Pressione o ícone de desbloqueio para abrir"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Desbloqueado pelo rosto. Pressione o ícone de desbloqueio para abrir."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Desbloqueado pelo rosto. Pressione para abrir."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Rosto reconhecido. Pressione para abrir."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Rosto reconhecido. Pressione o ícone de desbloq. para abrir."</string> <string name="keyguard_retry" msgid="886802522584053523">"Deslize para cima para tentar novamente"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloqueie para usar a NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertence à sua organização"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Quer continuar a sessão?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Recomeçar"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Sim, continuar"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Modo visitante"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Você está no modo visitante"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Adicionar novo usuário?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Quando você adiciona um novo usuário, essa pessoa precisa configurar o próprio espaço.\n\nQualquer usuário pode atualizar apps para os demais usuários."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Ao adicionar um novo usuário, o dispositivo vai sair do modo visitante e excluir todos os apps e dados da Sessão de visitante atual."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Limite de usuários atingido"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="one">É possível adicionar até <xliff:g id="COUNT">%d</xliff:g> usuário.</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Parear novo dispositivo"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Abra o app para transmitir esta sessão."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"App desconhecido"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Parar transmissão"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Como funciona a transmissão"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Transmitir"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"As pessoas próximas a você com dispositivos Bluetooth compatíveis podem ouvir a mídia que você está transmitindo"</string> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index d37b52bf5cde..a8b6ba8f616a 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmat"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Atingeți Confirmați pentru a finaliza"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"S-a deblocat cu ajutorul feței. Apăsați pictograma de deblocare pentru a continua"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"S-a deblocat cu ajutorul feței. Apăsați pentru a continua."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Chipul a fost recunoscut. Apăsați pentru a continua."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Chip recunoscut. Apăsați pictograma de deblocare să continuați."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentificat"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Folosiți PIN-ul"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Folosiți modelul"</string> @@ -314,6 +317,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Glisați în sus pentru a deschide"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Apăsați pictograma de deblocare pentru a deschide"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"S-a deblocat cu ajutorul feței. Apăsați pictograma de deblocare pentru a deschide"</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"S-a deblocat cu ajutorul feței. Apăsați pentru a deschide."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Chipul a fost recunoscut. Apăsați pentru a deschide."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Chip recunoscut. Apăsați pictograma de deblocare pentru a deschide"</string> <string name="keyguard_retry" msgid="886802522584053523">"Glisați pentru a încerca din nou"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Deblocați pentru a folosi NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Dispozitivul aparține organizației dvs."</string> @@ -340,6 +346,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Vreți să continuați sesiunea?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Începeți din nou"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Da, continuați"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Modul pentru invitați"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Folosiți modul pentru invitați"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Adăugați un utilizator nou?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Când adăugați un utilizator nou, acesta trebuie să-și configureze spațiul.\n\nOrice utilizator poate actualiza aplicațiile pentru toți ceilalți utilizatori."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Dacă adăugați un utilizator nou, veți ieși din modul pentru invitați și se vor șterge toate aplicațiile și datele din sesiunea pentru invitați actuală."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Ați atins limita de utilizatori"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="few">Puteți adăuga maximum <xliff:g id="COUNT">%d</xliff:g> utilizatori.</item> @@ -841,7 +852,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Asociați un nou dispozitiv"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Pentru a proiecta această sesiune, deschideți aplicația."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Aplicație necunoscută"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Nu mai proiectați"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Cum funcționează transmisia"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Transmiteți"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Persoanele din apropiere cu dispozitive Bluetooth compatibile pot asculta conținutul pe care îl transmiteți"</string> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index e1b48cd88376..8b51b0637075 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Подтверждено"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Нажмите \"Подтвердить\""</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Сканирование выполнено. Нажмите на значок разблокировки."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Разблокировано сканированием лица. Нажмите, чтобы продолжить."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Лицо распознано. Нажмите, чтобы продолжить."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Лицо распознано. Нажмите на значок разблокировки."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Аутентификация выполнена"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN-код"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Использовать графический ключ"</string> @@ -316,6 +319,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Проведите вверх, чтобы открыть"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Нажмите на значок разблокировки."</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Сканирование выполнено. Нажмите на значок разблокировки."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Разблокировано сканированием лица. Нажмите, чтобы открыть."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Лицо распознано. Нажмите, чтобы открыть."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Лицо распознано. Нажмите на значок разблокировки."</string> <string name="keyguard_retry" msgid="886802522584053523">"Чтобы повторить попытку, проведите вверх"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Чтобы использовать NFC, разблокируйте устройство."</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Это устройство принадлежит вашей организации"</string> @@ -342,6 +348,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Продолжить сеанс?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Начать заново"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Да, продолжить"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Гостевой режим"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Включен гостевой режим"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Добавить пользователя?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Когда вы добавите пользователя, ему потребуется настроить профиль.\n\nЛюбой пользователь устройства может обновлять приложения для всех аккаунтов."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Добавив нового пользователя, вы выйдете из гостевого режима. Все приложения и данные в текущем гостевом сеансе будут удалены."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Достигнут лимит"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="one">Можно добавить не более <xliff:g id="COUNT">%d</xliff:g> пользователя.</item> @@ -847,7 +858,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Подключить новое устройство"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Чтобы начать трансляцию сеанса, откройте приложение"</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Неизвестное приложение"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Остановить трансляцию"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Как работают трансляции"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Трансляция"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Находящиеся рядом с вами люди с совместимыми устройствами Bluetooth могут слушать медиафайлы, которые вы транслируете."</string> diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml index a3a8534d4136..ad878f0fbf11 100644 --- a/packages/SystemUI/res/values-si/strings.xml +++ b/packages/SystemUI/res/values-si/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"තහවුරු කළා"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"සම්පූර්ණ කිරීමට තහවුරු කරන්න තට්ටු කර."</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"මුහුණ මගින් අගුලු හරින ලදි. දිගටම කරගෙන යාමට අගුලු හැරීමේ නිරූපකය ඔබන්න."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"මුහුණ මගින් අගුලු හරින ලදි. ඉදිරියට යාමට ඔබන්න."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"මුහුණ හඳුනා ගන්නා ලදි. ඉදිරියට යාමට ඔබන්න."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"මුහුණ හඳුනා ගන්නා ලදි. ඉදිරියට යාමට අගුලු හැරීමේ නිරූපකය ඔබන්න."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"සත්යාපනය විය"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN භාවිත කරන්න"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"රටාව භාවිත කරන්න"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"විවෘත කිරීමට ස්වයිප් කරන්න"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"විවෘත කිරීමට අගුලු හැරීමේ නිරූපකය ඔබන්න"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"මුහුණ මගින් අගුලු හරින ලදි. විවෘත කිරීමට අගුලු හැරීමේ නිරූපකය ඔබන්න."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"මුහුණ මගින් අගුලු හරින ලදි. විවෘත කිරීමට ඔබන්න."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"මුහුණ හඳුනා ගන්නා ලදි. විවෘත කිරීමට ඔබන්න."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"මුහුණ හඳුනා ගන්නා ලදි. විවෘත කිරීමට අගුලු හැරීමේ නිරූපකය ඔබන්න."</string> <string name="keyguard_retry" msgid="886802522584053523">"නැවත උත්සාහ කිරීමට ඉහළට ස්වයිප් කරන්න"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC භාවිත කිරීමට අගුලු හරින්න"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"මෙම උපාංගය ඔබේ සංවිධානයට අයිතිය"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"ඔබගේ සැසිය දිගටම කරගෙන යෑමට ඔබට අවශ්යද?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"යළි මුල සිට අරඹන්න"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"ඔව්, දිගටම කරගෙන යන්න"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"ආගන්තුක ප්රකාරය"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"ඔබ ආගන්තුක ප්රකාරයේ සිටී"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"අලුත් පරිශීලකයෙක් එක් කරන්නද?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"ඔබ අලුත් පරිශීලකයෙක් එකතු කරන විට, එම පුද්ගලයා ඔහුගේ වැඩ කරන ඉඩ සකසා ගත යුතුය.\n\nසියළුම අනෙක් පරිශීලකයින් සඳහා ඕනෑම පරිශීලකයෙකුට යාවත්කාලීන කළ හැක."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"නව පරිශීලකයෙකු එක් කිරීම ආගන්තුක මාදිලියෙන් පිටවී වත්මන් ආගන්තුක සැසියෙන් සියලුම යෙදුම් සහ දත්ත මකනු ඇත."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"පරිශීලක සීමාවට ළඟා විය"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="one">ඔබට පරිශීලකයින් <xliff:g id="COUNT">%d</xliff:g>ක් දක්වා එක් කළ හැකිය.</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"නව උපාංගය යුගල කරන්න"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"මෙම සැසිය විකාශය කිරීමට, කරුණාකර යෙදුම විවෘත කරන්න."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"නොදන්නා යෙදුම"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"විකාශය නවතන්න"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"විකාශනය ක්රියා කරන ආකාරය"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"විකාශනය"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"ගැළපෙන බ්ලූටූත් උපාංග සහිත ඔබ අවට සිටින පුද්ගලයින්ට ඔබ විකාශනය කරන මාධ්යයට සවන් දිය හැකිය"</string> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index 2d468298a21f..60cc7132491a 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potvrdené"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Overenie dokončíte klepnutím na Potvrdiť"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Odomknuté tvárou. Pokračujte klepnutím na ikonu odomknutia"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Odomknuté tvárou. Pokračujte stlačením."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Tvár bola rozpoznaná. Pokračujte stlačením."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Tvár bola rozpoznaná. Pokračujte stlačením ikony odomknutia"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Overené"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Použiť PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Použiť vzor"</string> @@ -316,6 +319,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Otvorte potiahnutím prstom nahor"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Otvorte klepnutím na ikonu odomknutia"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Odomknuté tvárou. Otvorte klepnutím na ikonu odomknutia."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Odomknuté tvárou. Otvorte stlačením."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Tvár bola rozpoznaná. Otvorte stlačením."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Tvár bola rozpoznaná. Otvorte stlačením ikony odomknutia."</string> <string name="keyguard_retry" msgid="886802522584053523">"Potiahnutím nahor to skúste znova"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Ak chcete použiť NFC, odomknite"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Toto zariadenie patrí vašej organizácii"</string> @@ -342,6 +348,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Chcete v relácii pokračovať?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Začať odznova"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Áno, pokračovať"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Režim pre hostí"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Ste v režime pre hostí"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Pridať nového používateľa?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Keď pridáte nového používateľa, musí si nastaviť vlastný priestor.\n\nKtorýkoľvek používateľ môže aktualizovať aplikácie všetkých ostatných používateľov."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Ak pridáte nového používatelia, ukončí sa režim pre hostí a odstránia sa všetky aplikácie a údaje z aktuálnej relácie hosťa."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Dosiahnutý limit počtu používateľov"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="few">Môžete pridať maximálne <xliff:g id="COUNT">%d</xliff:g> používateľov.</item> @@ -847,7 +858,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Spárovať nové zariadenie"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Ak chcete túto reláciu prenášať, otvorte aplikáciu."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Neznáma aplikácia"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Zastaviť prenos"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Ako vysielanie funguje"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Vysielanie"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Ľudia v okolí s kompatibilnými zariadeniami s rozhraním Bluetooth si môžu vypočuť médiá, ktoré vysielate"</string> diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index aab95f10a162..9acc55e24564 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potrjeno"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Za dokončanje se dotaknite »Potrdite«"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Odklenjeno z obrazom. Za nadaljevanje pritisnite ikono za odklepanje."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Odklenjeno z obrazom. Pritisnite za nadaljevanje."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Obraz je prepoznan. Pritisnite za nadaljevanje."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Obraz je prepoznan. Za nadaljevanje pritisnite ikono za odklepanje."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Preverjena pristnost"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Uporabi kodo PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Uporabi vzorec"</string> @@ -316,6 +319,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Povlecite navzgor, da odprete"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Za odpiranje pritisnite ikono za odklepanje."</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Odklenjeno z obrazom. Za odpiranje pritisnite ikono za odklepanje."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Odklenjeno z obrazom. Pritisnite za odpiranje."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Obraz je prepoznan. Pritisnite za odpiranje."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Obraz je prepoznan. Za odpiranje pritisnite ikono za odklepanje."</string> <string name="keyguard_retry" msgid="886802522584053523">"Povlecite navzgor za vnovičen poskus"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Odklenite napravo, če želite uporabljati NFC."</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Ta naprava pripada vaši organizaciji"</string> @@ -342,6 +348,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Želite nadaljevati sejo?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Začni znova"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Da, nadaljuj"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Način za goste"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Ste v načinu za goste"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Dodajanje novega uporabnika?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Ko dodate novega uporabnika, mora ta nastaviti svoj prostor.\n\nVsak uporabnik lahko posodobi aplikacije za vse druge uporabnike."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Če dodate novega uporabnika, se bo način za goste zaprl, aplikacije in podatki v trenutni seji gosta pa bodo izbrisani."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Omejitev uporabnikov je dosežena"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="one">Dodate lahko do <xliff:g id="COUNT">%d</xliff:g> uporabnika.</item> @@ -847,7 +858,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Seznanitev nove naprave"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Če želite predvajati to sejo, odprite aplikacijo."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Neznana aplikacija"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Ustavi predvajanje"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Kako deluje oddajanje"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Oddajanje"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Osebe v bližini z združljivo napravo Bluetooth lahko poslušajo predstavnost, ki jo oddajate."</string> diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml index 42aae9f736cb..134c2c2308c4 100644 --- a/packages/SystemUI/res/values-sq/strings.xml +++ b/packages/SystemUI/res/values-sq/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Konfirmuar"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Trokit \"Konfirmo\" për ta përfunduar"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"U shkyç me fytyrë. Shtyp ikonën e shkyçjes për të vazhduar."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"U shkyç me fytyrë. Shtyp për të vazhduar."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Fytyra u njoh. Shtyp për të vazhduar."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Fytyra u njoh. Shtyp ikonën e shkyçjes për të vazhduar."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"U vërtetua"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Përdor kodin PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Përdor motivin"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Rrëshqit lart për ta hapur"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Shtyp ikonën e shkyçjes për ta hapur"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"U shkyç me fytyrë. Shtyp ikonën e shkyçjes për ta hapur."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"U shkyç me fytyrë. Shtyp për ta hapur."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Fytyra u njoh. Shtyp për ta hapur."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Fytyra u njoh. Shtyp ikonën e shkyçjes për ta hapur."</string> <string name="keyguard_retry" msgid="886802522584053523">"Rrëshqit lart për të provuar përsëri"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Shkyçe për të përdorur NFC-në"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Kjo pajisje i përket organizatës sate"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Dëshiron ta vazhdosh sesionin tënd?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Fillo nga e para"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Po, vazhdo"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Modaliteti \"vizitor\""</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Je në modalitetin \"vizitor\""</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Të shtohet përdorues i ri?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Kur shton një përdorues të ri, ai person duhet të konfigurojë hapësirën e vet.\n\nÇdo përdorues mund t\'i përditësojë aplikacionet për të gjithë përdoruesit e tjerë."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Shtimi i një përdoruesi të ri do të të nxjerrë nga modaliteti \"vizitor\" dhe do të fshijë të gjitha aplikacionet dhe të dhënat nga sesioni aktual për vizitorë."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"U arrit kufiri i përdoruesve"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">Mund të shtosh deri në <xliff:g id="COUNT">%d</xliff:g> përdorues.</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Çifto pajisjen e re"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Hap aplikacionin për të transmetuar këtë seancë."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Aplikacion i panjohur"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Ndalo transmetimin"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Si funksionon transmetimi"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Transmetimi"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Personat në afërsi me ty me pajisje të përputhshme me Bluetooth mund të dëgjojnë median që ti po transmeton"</string> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index 8b9b08841b3b..1ebc3a610172 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Потврђено"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Додирните Потврди да бисте завршили"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Откључано је лицем. Притисните икону откључавања за наставак"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Откључано је лицем. Притисните да бисте наставили."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Лице је препознато. Притисните да бисте наставили."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Лице препознато. Притисните икону откључавања за наставак."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Идентитет је потврђен"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Користите PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Користите шаблон"</string> @@ -314,6 +317,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Превуците нагоре да бисте отворили"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Притисните икону откључавања за отварање"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Откључано је лицем. Притисните икону откључавања за отварање"</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Откључано је лицем. Притисните да бисте отворили."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Лице је препознато. Притисните да бисте отворили."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Лице препознато. Притисните икону откључавања за отварање."</string> <string name="keyguard_retry" msgid="886802522584053523">"Превуците нагоре да бисте пробали поново"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Откључајте да бисте користили NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Овај уређај припада организацији"</string> @@ -340,6 +346,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Желите ли да наставите сесију?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Почни из почетка"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Да, настави"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Режим госта"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Користите режим госта"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Додајете новог корисника?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Када додате новог корисника, та особа треба да подеси свој простор.\n\nСваки корисник може да ажурира апликације за све остале кориснике."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Додавањем новог корисника изаћи ћете из режима госта и избрисаћете све апликације и податке из актуелне сесије госта."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Достигнут максимални број корисника"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="one">Можете да додате највише <xliff:g id="COUNT">%d</xliff:g> корисника.</item> @@ -841,7 +852,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Упари нови уређај"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Да бисте пребацивали ову сесију, отворите апликацију."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Непозната апликација"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Заустави пребацивање"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Како функционише емитовање"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Емитовање"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Људи у близини са компатибилним Bluetooth уређајима могу да слушају медијски садржај који емитујете"</string> diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index 9206685be801..44de3a475f2d 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bekräftat"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Slutför genom att trycka på Bekräfta"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Upplåst med ansiktslås. Tryck på ikonen lås upp för att fortsätta."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Upplåst med ansiktslås. Tryck för att fortsätta."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Ansiktet har identifierats. Tryck för att fortsätta."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Ansiktet har identifierats. Tryck på ikonen lås upp."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentiserad"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Använd pinkod"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Använd mönster"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Öppna genom att svepa uppåt"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Tryck på ikonen lås upp för att öppna"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Upplåst med ansiktslås. Tryck på ikonen lås upp för att öppna."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Upplåst med ansiktslås. Tryck för att öppna."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Ansiktet har identifierats. Tryck för att öppna."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Ansiktet har identifierats. Tryck på ikonen lås upp."</string> <string name="keyguard_retry" msgid="886802522584053523">"Svep uppåt om du vill försöka igen"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Lås upp om du vill använda NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Den här enheten tillhör organisationen"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Vill du fortsätta sessionen?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Börja om"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Ja, fortsätt"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Gästläge"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Du är i gästläge"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Lägga till ny användare?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"När du lägger till en ny användare måste den personen konfigurera sitt utrymme.\n\nAlla användare kan uppdatera appar för samtliga användares räkning."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Om du lägger till en ny användare avslutas gästläget och alla appar och all data från den aktuella gästsessionen raderas."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Användargränsen har nåtts"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">Det går att lägga till upp till <xliff:g id="COUNT">%d</xliff:g> användare.</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Parkoppla en ny enhet"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Öppna appen om du vill casta den här sessionen."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Okänd app"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Sluta casta"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Så fungerar utsändning"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Utsändning"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Personer i närheten med kompatibla Bluetooth-enheter kan lyssna på medieinnehåll som du sänder ut"</string> diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index ad5d132f2fcb..e6f3e1794bd9 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Imethibitishwa"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Gusa Thibitisha ili ukamilishe"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Imefunguliwa kwa kutumia uso wako. Bonyeza aikoni ya kufungua ili uendelee."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Imefunguliwa kwa kutumia uso wako. Bonyeza ili uendelee."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Uso umetambuliwa. Bonyeza ili uendelee."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Uso umetambuliwa. Bonyeza aikoni ya kufungua ili uendelee."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Umethibitishwa"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Tumia PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Tumia mchoro"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Telezesha kidole juu ili ufungue"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Bonyeza aikoni ya kufungua ili ufungue"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Imefunguliwa kwa kutumia uso wako. Bonyeza aikoni ya kufungua ili ufungue."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Imefunguliwa kwa kutumia uso wako. Bonyeza ili ufungue."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Uso umetambuliwa. Bonyeza ili ufungue."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Uso umetambuliwa. Bonyeza aikoni ya kufungua ili ufungue."</string> <string name="keyguard_retry" msgid="886802522584053523">"Telezesha kidole juu ili ujaribu tena"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Fungua ili utumie NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Kifaa hiki kinamilikiwa na shirika lako"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Je, unataka kuendelea na kipindi chako?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Anza upya"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Ndiyo, endelea"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Matumizi ya wageni"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Unatumia hali ya wageni"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Ungependa kuongeza mtumiaji?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Mtumiaji mpya utakayemwongeza atahitaji kuongeza akaunti yake.\n\nMtumiaji yoyote anaweza kusasisha programu kwa niaba ya wengine wote."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Kuongeza mtumiaji mpya kutaondoa matumizi ya wageni yaliyopo na kufuta programu na data kutoka kwenye kipindi cha mgeni cha sasa."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Umefikia kima cha juu cha watumiaji"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">Unaruhusiwa kuongeza hadi watumiaji <xliff:g id="COUNT">%d</xliff:g>.</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Oanisha kifaa kipya"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Ili utume kipindi hiki, tafadhali fungua programu."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Programu isiyojulikana"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Acha kutuma"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Jinsi utangazaji unavyofanya kazi"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Tangaza"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Watu walio karibu nawe wenye vifaa oanifu vya Bluetooth wanaweza kusikiliza maudhui unayoyatangaza"</string> diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml index d66bc4117897..776e205b9668 100644 --- a/packages/SystemUI/res/values-ta/strings.xml +++ b/packages/SystemUI/res/values-ta/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"உறுதிப்படுத்தப்பட்டது"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"முடிக்க \'உறுதிப்படுத்துக\' என்பதை தட்டவும்"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"முகம் மூலம் அன்லாக் செய்யப்பட்டது. தொடர, அன்லாக் ஐகானை அழுத்துக."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"அங்கீகரிக்கப்பட்டது"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"பின்னைப் பயன்படுத்து"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"பேட்டர்னைப் பயன்படுத்து"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"திறப்பதற்கு மேல் நோக்கி ஸ்வைப் செய்யவும்"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"திறக்க, அன்லாக் ஐகானை அழுத்தவும்"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"முகம் மூலம் அன்லாக் செய்யப்பட்டது. திறக்க, அன்லாக் ஐகானை அழுத்துக."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"மீண்டும் முயல மேல்நோக்கி ஸ்வைப் செய்யவும்"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFCயைப் பயன்படுத்த அன்லாக் செய்யவும்"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"இந்த சாதனம் உங்கள் நிறுவனத்துக்கு சொந்தமானது"</string> @@ -338,6 +350,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"உங்கள் அமர்வைத் தொடர விருப்பமா?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"மீண்டும் தொடங்கு"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"தொடரவும்"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"கெஸ்ட் பயன்முறை"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"கெஸ்ட் பயன்முறையில் உள்ளீர்கள்"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"புதியவரைச் சேர்க்கவா?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"புதிய பயனரைச் சேர்க்கும்போது, அவர் தனக்கான இடத்தை அமைக்க வேண்டும்.\n\nஎந்தவொரு பயனரும், மற்ற எல்லா பயனர்களுக்காகவும் ஆப்ஸைப் புதுப்பிக்கலாம்."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"புதிய பயனரைச் சேர்த்தால் கெஸ்ட் பயன்முறையில் இருந்து வெளியேற்றப்படுவீர்கள். மேலும் தற்போதைய கெஸ்ட் அமர்வின் ஆப்ஸ் மற்றும் தரவு அனைத்தும் நீக்கப்படும்."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"பயனர் வரம்பை அடைந்துவிட்டீர்கள்"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> பயனர்கள் வரை சேர்க்க முடியும்.</item> @@ -836,7 +853,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"புதிய சாதனத்தை இணைத்தல்"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"இந்த அமர்வை அலைபரப்ப ஆப்ஸைத் திறங்கள்."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"அறியப்படாத ஆப்ஸ்"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"அலைபரப்புவதை நிறுத்து"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"பிராட்காஸ்ட் எவ்வாறு செயல்படுகிறது?"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"பிராட்காஸ்ட்"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"நீங்கள் பிராட்காஸ்ட் செய்யும் மீடியாவை அருகிலுள்ளவர்கள் இணக்கமான புளூடூத் சாதனங்கள் மூலம் கேட்கலாம்"</string> diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml index 871282538090..93b5f7fc74f5 100644 --- a/packages/SystemUI/res/values-te/strings.xml +++ b/packages/SystemUI/res/values-te/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"నిర్ధారించబడింది"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"పూర్తి చేయడానికి \"నిర్ధారించు\" నొక్కండి"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"ముఖం ద్వారా అన్లాక్ చేయబడింది. కొనసాగించడానికి అన్లాక్ చిహ్నాన్ని నొక్కండి."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"ప్రామాణీకరించబడింది"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"పిన్ను ఉపయోగించు"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ఆకృతిని ఉపయోగించు"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"తెరవడానికి, పైకి స్వైప్ చేయండి"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"తెరవడానికి అన్లాక్ చిహ్నాన్ని నొక్కండి"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"ముఖం ద్వారా అన్లాక్ చేయబడింది. తెరవడానికి అన్లాక్ చిహ్నాన్ని నొక్కండి."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"మళ్ళీ ప్రయత్నించడానికి పైకి స్వైప్ చేయండి"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFCని ఉపయోగించడానికి అన్లాక్ చేయండి"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ఈ పరికరం మీ సంస్థకు చెందినది"</string> @@ -338,6 +350,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"మీరు మీ సెషన్ని కొనసాగించాలనుకుంటున్నారా?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"మొదటి నుండి ప్రారంభించు"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"అవును, కొనసాగించు"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"గెస్ట్ మోడ్"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"మీరు గెస్ట్ మోడ్లో ఉన్నారు"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"కొత్త యూజర్ను జోడించాలా?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"ఒక కొత్త యూజర్ను మీరు జోడించినప్పుడు, ఆ వ్యక్తి తన స్పేస్ను సెటప్ చేసుకోవాలి.\n\nఏ యూజర్ అయినా మిగతా అందరు యూజర్ల కోసం యాప్లను అప్డేట్ చేయగలరు."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"కొత్త యూజర్ను జోడించడం వలన గెస్ట్ మోడ్ నుండి నిష్క్రమించబడుతుంది, ప్రస్తుత గెస్ట్ సెషన్ నుండి అన్ని యాప్లు, డేటా తొలగించండి."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"వినియోగదారు పరిమితిని చేరుకున్నారు"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">మీరు <xliff:g id="COUNT">%d</xliff:g> వినియోగదారుల వరకు జోడించవచ్చు.</item> @@ -836,7 +853,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"కొత్త పరికరాన్ని పెయిర్ చేయండి"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"ఈ సెషన్ను ప్రసారం చేయడానికి, దయచేసి యాప్ను తెరవండి."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"తెలియని యాప్"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"ప్రసారాన్ని ఆపివేయండి"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ప్రసారం కావడం అనేది ఎలా పని చేస్తుంది"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"ప్రసారం"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"మీకు సమీపంలో ఉన్న వ్యక్తులు అనుకూలత ఉన్న బ్లూటూత్ పరికరాలతో మీరు ప్రసారం చేస్తున్న మీడియాను వినగలరు"</string> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index 434c4f01c3a4..3ca5697c832a 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ยืนยันแล้ว"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"แตะยืนยันเพื่อดำเนินการให้เสร็จสมบูรณ์"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"ปลดล็อกด้วยใบหน้าแล้ว กดไอคอนปลดล็อกเพื่อดำเนินการต่อ"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"ปลดล็อกด้วยใบหน้าแล้ว กดเพื่อดำเนินการต่อ"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"จดจำใบหน้าได้ กดเพื่อดำเนินการต่อ"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"จดจำใบหน้าได้ กดไอคอนปลดล็อกเพื่อดำเนินการต่อ"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"ตรวจสอบสิทธิ์แล้ว"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"ใช้ PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ใช้รูปแบบ"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"เลื่อนขึ้นเพื่อเปิด"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"กดไอคอนปลดล็อกเพื่อเปิด"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"ปลดล็อกด้วยใบหน้าแล้ว กดไอคอนปลดล็อกเพื่อเปิด"</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"ปลดล็อกด้วยใบหน้าแล้ว กดเพื่อเปิด"</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"จดจำใบหน้าได้ กดเพื่อเปิด"</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"จดจำใบหน้าได้ กดไอคอนปลดล็อกเพื่อเปิด"</string> <string name="keyguard_retry" msgid="886802522584053523">"เลื่อนขึ้นเพื่อลองอีกครั้ง"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"ปลดล็อกเพื่อใช้ NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"องค์กรของคุณเป็นเจ้าของอุปกรณ์นี้"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"คุณต้องการอยู่ในเซสชันต่อไปไหม"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"เริ่มต้นใหม่"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"ใช่ ดำเนินการต่อ"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"โหมดผู้มาเยือน"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"คุณอยู่ในโหมดผู้มาเยือน"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"ต้องการเพิ่มผู้ใช้ใหม่ใช่ไหม"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"เมื่อคุณเพิ่มผู้ใช้ใหม่ ผู้ใช้ดังกล่าวจะต้องตั้งค่าพื้นที่ของตนเอง\n\nผู้ใช้ทุกคนสามารถอัปเดตแอปสำหรับผู้ใช้รายอื่นทุกคนได้"</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"การเพิ่มผู้ใช้ใหม่จะเป็นการออกจากโหมดผู้มาเยือน และจะลบแอปและข้อมูลจากเซสชันผู้มาเยือนในปัจจุบัน"</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"ถึงขีดจำกัดผู้ใช้แล้ว"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">คุณเพิ่มผู้ใช้ได้สูงสุด <xliff:g id="COUNT">%d</xliff:g> คน</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"จับคู่อุปกรณ์ใหม่"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"โปรดเปิดแอปหากต้องการแคสต์เซสชันนี้"</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"แอปที่ไม่รู้จัก"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"หยุดแคสต์"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"วิธีการทำงานของการออกอากาศ"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"ประกาศ"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"ผู้ที่อยู่ใกล้คุณและมีอุปกรณ์บลูทูธที่รองรับสามารถรับฟังสื่อที่คุณกำลังออกอากาศได้"</string> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index 65c09eb558ea..145d12f27b0c 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Nakumpirma"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"I-tap ang Kumpirmahin para kumpletuhin"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Na-unlock gamit ang mukha. Pindutin ang icon ng unlock para magpatuloy."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Na-unlock gamit ang mukha. Pindutin para magpatuloy."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Nakilala ang mukha. Pindutin para magpatuloy."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Nakilala ang mukha. Pindutin ang unlock para magpatuloy."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Na-authenticate"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Gumamit ng PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Gumamit ng pattern"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Mag-swipe pataas para buksan"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Pindutin ang icon ng unlock para buksan"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Na-unlock gamit ang mukha. Pindutin ang icon ng unlock para buksan."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Na-unlock gamit ang mukha. Pindutin para buksan."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Nakilala ang mukha. Pindutin para buksan."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Nakilala ang mukha. Pindutin ang icon ng unlock para buksan."</string> <string name="keyguard_retry" msgid="886802522584053523">"Mag-swipe pataas para subukan ulit"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"I-unlock para magamit ang NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Pagmamay-ari ng iyong organisasyon ang device na ito"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Gusto mo bang ipagpatuloy ang iyong session?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Magsimulang muli"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Oo, magpatuloy"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Guest mode"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Naka-guest mode ka"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Magdagdag ng bagong user?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Kapag nagdagdag ka ng bagong user, kailangang i-set up ng taong iyon ang kanyang espasyo.\n\nAng sinumang user ay maaaring mag-update ng mga app para sa lahat ng iba pang user."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Kapag nagdagdag ka ng bagong user, aalis sa guest mode at made-delete ang lahat ng app at data mula sa kasalukuyang session ng bisita."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Naabot na ang limitasyon sa user"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="one">Maaari kang magdagdag ng hanggang <xliff:g id="COUNT">%d</xliff:g> user.</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Magpares ng bagong device"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Para ma-cast ang session na ito, buksan ang app."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Hindi kilalang app"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Ihinto ang pag-cast"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Paano gumagana ang pag-broadcast"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Broadcast"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Makakapakinig ang mga taong malapit sa iyo na may mga compatible na Bluetooth device sa media na bino-broadcast mo"</string> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index b7415fd4ee94..c0fc34144a25 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Onaylandı"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tamamlamak için Onayla\'ya dokunun"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Kilit, yüzünüzle açıldı. Kilit açma simgesine basın."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Kimliği Doğrulandı"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN kullan"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Deseni kullan"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Açmak için yukarı kaydırın"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Açmak için Kilit açma simgesine basın"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Kilit, yüzünüzle açıldı. Kilit açma simgesine basın."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"Tekrar denemek için yukarı kaydırın"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC\'yi kullanmak için kilidi açın"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Bu cihaz, kuruluşunuza ait"</string> @@ -338,6 +350,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Oturumunuza devam etmek istiyor musunuz?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Baştan başla"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Evet, devam et"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Misafir modu"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Misafir modundasınız"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Yeni kullanıcı eklensin mi?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Yeni bir kullanıcı eklediğinizde, bu kişinin kendi alanını ayarlaması gerekir.\n\nHerhangi bir kullanıcı, diğer tüm kullanıcılar için uygulamaları güncelleyebilir."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Yeni bir kullanıcı eklendiğinde misafir modundan çıkılarak mevcut misafir oturumundaki tüm uygulamalar ve veriler silinir."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Kullanıcı sınırına ulaşıldı"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">En fazla <xliff:g id="COUNT">%d</xliff:g> kullanıcı ekleyebilirsiniz.</item> @@ -836,7 +853,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Yeni cihaz eşle"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Bu oturumu yayınlamak için lütfen uygulamayı açın."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Bilinmeyen uygulama"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Yayını durdur"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Yayınlamanın işleyiş şekli"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Anons"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Yakınınızda ve uyumlu Bluetooth cihazları olan kişiler yayınladığınız medya içeriğini dinleyebilir"</string> diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index 7a2419117d2e..95c1e5203d5f 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Підтверджено"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Щоб завершити, натисніть \"Підтвердити\""</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Розблоковано (фейсконтроль). Натисніть значок розблокування."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Автентифіковано"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Ввести PIN-код"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Намалювати ключ"</string> @@ -316,6 +322,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Проведіть пальцем угору, щоб відкрити"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Щоб відкрити, натисніть значок розблокування."</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Розблоковано (фейсконтроль). Натисніть значок розблокування."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"Проведіть пальцем угору, щоб повторити спробу"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Розблокуйте екран, щоб скористатись NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Цей пристрій належить вашій організації"</string> @@ -342,6 +354,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Продовжити сеанс?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Почати знову"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Так, продовжити"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Режим гостя"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Ви ввійшли в режимі гостя"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Додати нового користувача?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Користувач має налаштувати свій профіль після створення.\n\nБудь-який користувач пристрою може оновлювати додатки для решти користувачів."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Якщо додати нового користувача, ви вийдете з режиму гостя, а всі додатки й дані з поточного сеансу цього режиму буде видалено."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Ви досягли ліміту користувачів"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="one">Можна додати до <xliff:g id="COUNT">%d</xliff:g> користувача.</item> @@ -848,7 +865,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Підключити новий пристрій"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Щоб транслювати цей сеанс, відкрийте додаток."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Невідомий додаток"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Припинити трансляцію"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Як працює трансляція"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Трансляція"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Люди поблизу, які мають сумісні пристрої з Bluetooth, можуть слухати медіаконтент, який ви транслюєте."</string> diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml index 6ba3c4fa3163..97c0a5529b16 100644 --- a/packages/SystemUI/res/values-ur/strings.xml +++ b/packages/SystemUI/res/values-ur/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"تصدیق شدہ"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"مکمل کرنے کیلئے \'تصدیق کریں\' تھپتھپائیں"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"چہرے سے انلاک کیا گیا۔ جاری رکھنے کیلئے انلاک آئیکن دبائیں۔"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"چہرے سے انلاک کیا گیا۔ جاری رکھنے کے لیے دبائیں۔"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"چہرے کی شناخت ہو گئی۔ جاری رکھنے کے لیے دبائیں۔"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"چہرے کی شناخت ہو گئی۔ جاری رکھنے کیلئے انلاک آئیکن دبائیں۔"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"تصدیق کردہ"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN استعمال کریں"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"پیٹرن کا استعمال کریں"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"کھولنے کے لیے اوپر سوائپ کريں"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"کھولنے کیلئے انلاک آئیکن دبائیں"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"چہرے سے انلاک کیا گیا۔ کھولنے کیلئے انلاک آئیکن دبائیں۔"</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"چہرے سے انلاک کیا گیا۔ کھولنے کے لیے دبائیں۔"</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"چہرے کی شناخت ہو گئی۔ کھولنے کے لیے دبائیں۔"</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"چہرے کی شناخت ہو گئی۔ کھولنے کیلئے انلاک آئیکن دبائیں۔"</string> <string name="keyguard_retry" msgid="886802522584053523">"دوبارہ کوشش کرنے کے لیے اوپر سوائپ کريں"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC استعمال کرنے کیلئے غیر مقفل کریں"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"یہ آلہ آپ کی تنظیم کا ہے"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"کیا آپ اپنا سیشن جاری رکھنا چاہتے ہیں؟"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"دوبارہ شروع کریں"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"ہاں، جاری رکھیں"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"مہمان وضع"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"آپ مہمان وضع میں ہیں"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"نیا صارف شامل کریں؟"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"جب آپ ایک نیا صارف شامل کرتے ہیں تو اس شخص کو اپنی جگہ کو ترتیب دینے کی ضرورت ہوتی ہے۔\n\nکوئی بھی صارف دیگر سبھی صارفین کیلئے ایپس کو اپ ڈیٹ کر سکتا ہے۔"</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"نئے صارف کو شامل کرنے سے مہمان وضع سے باہر نکل جائے گا اور موجودہ مہمان سیشن سے تمام ایپس اور ڈیٹا حذف ہو جائیں گے۔"</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"صارف کی حد مکمل ہو گئی"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">صرف <xliff:g id="COUNT">%d</xliff:g> صارفین بنائے جا سکتے ہیں۔</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"نئے آلہ کا جوڑا بنائیں"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"اس سیشن کو کاسٹ کرنے کیلئے، براہ کرم ایپ کھولیں۔"</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"نامعلوم ایپ"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"کاسٹ کرنا بند کریں"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"براڈکاسٹنگ کیسے کام کرتا ہے"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"براڈکاسٹ"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"موافق بلوٹوتھ آلات کے ساتھ آپ کے قریبی لوگ آپ کے نشر کردہ میڈیا کو سن سکتے ہیں"</string> diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml index a2831e036505..d94eff370dbc 100644 --- a/packages/SystemUI/res/values-uz/strings.xml +++ b/packages/SystemUI/res/values-uz/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Tasdiqlangan"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tasdiqlash uchun tegining"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Yuz orqali ochilgan. Davom etish uchun ochish belgisini bosing."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Tasdiqlandi"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN kod kiritish"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Grafik kalitdan foydalanish"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Ochish uchun tepaga suring"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Ochish uchun ochish belgisini bosing"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Yuz orqali ochilgan. Ochish uchun ochish belgisini bosing."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"Qayta urinish uchun tepaga suring"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ishlatish uchun qurilma qulfini oching"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Bu qurilma tashkilotingizga tegishli"</string> @@ -338,6 +350,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Seansni davom ettirmoqchimisiz?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Boshidan boshlansin"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Ha, davom ettirilsin"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Mehmon rejimi"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Mehmon rejimidasiz"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Foydalanuvchi qo‘shilsinmi?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Yangi profil qo‘shilgach, uni sozlash lozim.\n\nQurilmaning istalgan foydalanuvchisi ilovalarni barcha hisoblar uchun yangilashi mumkin."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Yangi foydalanuvchi kiritilsa, mehmon rejimi tark etiladi va joriy mehmon seansidagi barcha ilova va ularning maʼlumotlari tozalanadi."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Limitga yetib keldi"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> tagacha foydalanuvchi qo‘shish mumkin.</item> @@ -836,7 +853,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Yangi qurilmani ulash"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Bu seansni translatsiya qilish uchun ilovani oching."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Notanish ilova"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Toʻxtatish"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Translatsiya qanday ishlaydi"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Translatsiya"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Atrofingizdagi mos Bluetooth qurilmasiga ega foydalanuvchilar siz translatsiya qilayotgan mediani tinglay olishadi"</string> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index ef782a2a9c77..7b2115ae5d0f 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Ðã xác nhận"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Nhấn vào Xác nhận để hoàn tất"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Đã mở khoá bằng khuôn mặt. Nhấn biểu tượng mở khoá để tiếp tục."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Đã xác thực"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Dùng mã PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Dùng hình mở khóa"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Vuốt lên để mở"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Nhấn biểu tượng mở khoá để mở"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Đã mở khoá bằng khuôn mặt. Nhấn biểu tượng mở khoá để mở."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"Vuốt lên để thử lại"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Mở khóa để sử dụng NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Thiết bị này thuộc về tổ chức của bạn"</string> @@ -338,6 +350,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Bạn có muốn tiếp tục phiên của mình không?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Bắt đầu lại"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Có, tiếp tục"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Chế độ khách"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Bạn đang ở chế độ khách"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Thêm người dùng mới?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Khi bạn thêm người dùng mới, họ cần thiết lập không gian của mình.\n\nMọi người dùng đều có thể cập nhật ứng dụng cho tất cả người dùng khác."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Khi thêm người dùng mới, chế độ khách sẽ bị thoát và mọi ứng dụng cũng như dữ liệu trong phiên khách hiện tại sẽ bị xoá."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Đã đạt đến giới hạn người dùng"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">Bạn có thể thêm tối đa <xliff:g id="COUNT">%d</xliff:g> người dùng.</item> @@ -836,7 +853,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Ghép nối thiết bị mới"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Vui lòng mở ứng dụng để truyền phiên này."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"Ứng dụng không xác định"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Dừng truyền"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Cách tính năng truyền hoạt động"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Truyền"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Những người ở gần có thiết bị Bluetooth tương thích có thể nghe nội dung nghe nhìn bạn đang truyền"</string> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index ac1b79087b08..880f8eb637d1 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"已确认"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"点按“确认”即可完成"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"已通过面孔识别解锁。按下解锁图标即可继续。"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"已通过面孔识别解锁。点按即可继续。"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"识别出面孔。点按即可继续。"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"识别出面孔。按下解锁图标即可继续。"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"已经过身份验证"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"使用 PIN 码"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"使用图案"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"向上滑动即可打开"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"按下解锁图标即可打开"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"已通过面孔识别解锁。按下解锁图标即可打开。"</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"已通过面孔识别解锁。点按即可打开。"</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"识别出面孔。点按即可打开。"</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"识别出面孔。按下解锁图标即可打开。"</string> <string name="keyguard_retry" msgid="886802522584053523">"向上滑动即可重试"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"需要解锁才能使用 NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"此设备归贵单位所有"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"要继续您的会话吗?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"重新开始"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"是,继续"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"访客模式"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"您当前处于访客模式"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"要添加新用户吗?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"当您添加新用户时,该用户必须设置自己的空间。\n\n任何用户均可为其他所有用户更新应用。"</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"如果添加新用户,系统将退出访客模式并删除当前访客会话中的所有应用和数据。"</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"已达到用户数上限"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">您最多可以添加 <xliff:g id="COUNT">%d</xliff:g> 位用户。</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"与新设备配对"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"如需投射此会话,请打开相关应用。"</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"未知应用"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"停止投射"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"广播的运作方式"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"广播"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"附近使用兼容蓝牙设备的用户可以收听您广播的媒体内容"</string> diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index 436e29389694..2050e96e1362 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"已確認"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"輕按 [確定] 以完成"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"已使用面孔解鎖。按解鎖圖示即可繼續。"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"已使用面孔解鎖。按下即可繼續操作。"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"已識別面孔。按下即可繼續操作。"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"已識別面孔。按解鎖圖示即可繼續。"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"驗證咗"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"使用 PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"使用圖案"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"向上滑動即可開啟"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"按解鎖圖示即可開啟"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"已使用面孔解鎖。按解鎖圖示即可開啟。"</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"已使用面孔解鎖。按下即可開啟。"</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"已識別面孔。按下即可開啟。"</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"已識別面孔。按解鎖圖示即可開啟。"</string> <string name="keyguard_retry" msgid="886802522584053523">"請向上滑動以再試一次"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"解鎖方可使用 NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"此裝置屬於您的機構"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"您要繼續您的工作階段嗎?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"重新開始"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"是的,請繼續"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"訪客模式"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"您正在使用訪客模式"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"新增使用者?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"新增的使用者需要自行設定個人空間。\n\n任何使用者均可為所有其他使用者更新應用程式。"</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"新增使用者後,系統就會結束訪客模式,並刪除目前訪客工作階段中的所有應用程式和資料。"</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"已達到使用者上限"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">您可以加入多達 <xliff:g id="COUNT">%d</xliff:g> 個使用者。</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"配對新裝置"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"如要投放此工作階段,請開啟應用程式。"</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"不明應用程式"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"停止投放"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"廣播運作方式"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"廣播"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"附近有兼容藍牙裝置的人可收聽您正在廣播的媒體內容"</string> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index 297715d64e15..40b3aa677779 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"確認完畢"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"輕觸 [確認] 完成驗證設定"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"裝置已透過人臉解鎖,按下「解鎖」圖示即可繼續操作。"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"裝置已透過你的臉解鎖,按下即可繼續操作。"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"臉孔辨識完成,按下即可繼續操作。"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"臉孔辨識完成,按下「解鎖」圖示即可繼續操作。"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"已通過驗證"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"使用 PIN 碼"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"使用解鎖圖案"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"向上滑動即可開啟"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"按下「解鎖」圖示即可開啟"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"裝置已透過人臉解鎖,按下「解鎖」圖示即可開啟。"</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"裝置已透過你的臉解鎖,按下即可開啟。"</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"臉孔辨識完成,按下即可開啟。"</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"臉孔辨識完成,按下「解鎖」圖示即可開啟。"</string> <string name="keyguard_retry" msgid="886802522584053523">"向上滑動即可重試"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"如要使用 NFC,請先解鎖"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"這部裝置的擁有者為貴機構"</string> @@ -338,6 +344,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"你要繼續這個工作階段嗎?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"重新開始"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"是,繼續"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"訪客模式"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"你目前處於訪客模式"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"要新增使用者嗎?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"新增的使用者需要自行設定個人空間。\n\n任何使用者皆可為其他所有使用者更新應用程式。"</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"新增使用者後,系統就會結束訪客模式,並刪除目前訪客工作階段中的所有應用程式和資料。"</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"已達使用者數量上限"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="other">最多可新增 <xliff:g id="COUNT">%d</xliff:g> 位使用者。</item> @@ -835,7 +846,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"配對新裝置"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"如要投放這個工作階段,請開啟應用程式。"</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"不明的應用程式"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"停止投放"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"廣播功能的運作方式"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"廣播"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"如果附近的人有相容的藍牙裝置,就可以聽到你正在廣播的媒體內容"</string> diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index d932406f1059..8d0b10c353d0 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Kuqinisekisiwe"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Thepha okuthi Qinisekisa ukuze uqedele"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Ivulwe ngobuso. Cindezela isithonjana sokuvula ukuze uqhubeke."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Kugunyaziwe"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Sebenzisa iphinikhodi"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Sebenzisa iphethini"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Swayiphela phezulu ukuze uvule"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Cindezela isithonjana sokuvula ukuze uvule"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Ivulwe ngobuso. Cindezela isithonjana sokuvula ukuze uvule."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"Swayiphela phezulu ukuze uzame futhi"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Vula ukuze usebenzise i-NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Le divayisi eyenhlangano yakho"</string> @@ -338,6 +350,11 @@ <string name="guest_wipe_session_message" msgid="3393823610257065457">"Ingabe ufuna ukuqhubeka ngesikhathi sakho?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Qala phansi"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Yebo, qhubeka"</string> + <string name="guest_notification_app_name" msgid="2110425506754205509">"Imodi yesivakashi"</string> + <string name="guest_notification_session_active" msgid="5567273684713471450">"Usemodini yesivakashi"</string> + <string name="user_add_user_title" msgid="4172327541504825032">"Engeza umsebenzisi omusha?"</string> + <string name="user_add_user_message_short" msgid="2599370307878014791">"Uma ungeza umsebenzisi omusha, loyo muntu udinga ukusetha isikhala sakhe.\n\nNoma yimuphi umsebenzisi angabuyekeza izinhlelo zokusebenza kubo bonke abasebenzisi."</string> + <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Ukwengeza umsebenzisi omusha kuzokhipha imodi yesivakashi futhi kusule wonke ama-app nedatha kusuka esikhathini sesihambeli samanje."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Kufinyelelwe kumkhawulo womsebenzisi"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> <item quantity="one">Ungangeza kufikela kubasebenzisi abangu-<xliff:g id="COUNT">%d</xliff:g>.</item> @@ -836,7 +853,6 @@ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Bhangqa idivayisi entsha"</string> <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"Ukuze usakaze le seshini, sicela uvule i-app."</string> <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"I-app engaziwa"</string> - <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Misa ukusakaza"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Indlela ukusakaza okusebenza ngayo"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Sakaza"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Abantu abaseduze nawe abanamadivayisi e-Bluetooth ahambisanayo bangalalela imidiya oyisakazayo"</string> diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index 02ba271ee9a4..2c04ee731b3a 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -180,12 +180,10 @@ <!-- media output dialog--> <color name="media_dialog_background" android:lstar="98">@color/material_dynamic_neutral90</color> - <color name="media_dialog_item_main_content">@color/material_dynamic_primary20</color> + <color name="media_dialog_active_item_main_content">@color/material_dynamic_primary10</color> + <color name="media_dialog_inactive_item_main_content">@color/material_dynamic_primary40</color> + <color name="media_dialog_item_status">@color/material_dynamic_primary10</color> <color name="media_dialog_item_background">@color/material_dynamic_secondary95</color> - <color name="media_dialog_connected_item_background">@color/material_dynamic_primary90</color> - <color name="media_dialog_seekbar_progress">@color/material_dynamic_secondary40</color> - <color name="media_dialog_button_background">@color/material_dynamic_primary40</color> - <color name="media_dialog_solid_button_text">@color/material_dynamic_neutral95</color> <!-- controls --> <color name="control_primary_text">#E6FFFFFF</color> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 83b1b52fff3d..9e6b277025eb 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -438,6 +438,9 @@ they were added. --> <integer name="config_smart_replies_in_notifications_onclick_init_delay">200</integer> + <!-- Smartspace trampoline activity that is used when the user taps smartspace. --> + <string name="config_smartspaceTrampolineActivityComponent" translatable="false">com.google.android.apps.gsa.staticplugins.opa.smartspace.ExportedSmartspaceTrampolineActivity</string> + <!-- Screenshot editing default activity. Must handle ACTION_EDIT image/png intents. Blank sends the user to the Chooser first. This name is in the ComponentName flattened format (package/class) --> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index f92d6238e863..47f287950bfe 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -339,6 +339,12 @@ <string name="biometric_dialog_tap_confirm">Tap Confirm to complete</string> <!-- Message shown when a biometric has authenticated with a user's face and is waiting for the user to confirm authentication [CHAR LIMIT=60]--> <string name="biometric_dialog_tap_confirm_with_face">Unlocked by face. Press the unlock icon to continue.</string> + <!-- Message shown when a biometric has authenticated with a user's face and is waiting for the user to confirm authentication [CHAR LIMIT=60]--> + <string name="biometric_dialog_tap_confirm_with_face_alt_1">Unlocked by face. Press to continue.</string> + <!-- Message shown when a biometric has authenticated with a user's face and is waiting for the user to confirm authentication [CHAR LIMIT=60]--> + <string name="biometric_dialog_tap_confirm_with_face_alt_2">Face recognized. Press to continue.</string> + <!-- Message shown when a biometric has authenticated with a user's face and is waiting for the user to confirm authentication [CHAR LIMIT=60]--> + <string name="biometric_dialog_tap_confirm_with_face_alt_3">Face recognized. Press the unlock icon to continue.</string> <!-- Talkback string when a biometric is authenticated [CHAR LIMIT=NONE] --> <string name="biometric_dialog_authenticated">Authenticated</string> @@ -801,6 +807,13 @@ <!-- Message shown when non-bypass face authentication succeeds and UDFPS is supported. Provides extra instructions for how the user can enter their device [CHAR LIMIT=60] --> <string name="keyguard_face_successful_unlock_press">Unlocked by face. Press the unlock icon to open.</string> + <!-- Message shown when non-bypass face authentication succeeds and UDFPS is supported. Provides extra instructions for how the user can enter their device [CHAR LIMIT=60] --> + <string name="keyguard_face_successful_unlock_press_alt_1">Unlocked by face. Press to open.</string> + <!-- Message shown when non-bypass face authentication succeeds and UDFPS is supported. Provides extra instructions for how the user can enter their device [CHAR LIMIT=60] --> + <string name="keyguard_face_successful_unlock_press_alt_2">Face recognized. Press to open.</string> + <!-- Message shown when non-bypass face authentication succeeds and UDFPS is supported. Provides extra instructions for how the user can enter their device [CHAR LIMIT=60] --> + <string name="keyguard_face_successful_unlock_press_alt_3">Face recognized. Press the unlock icon to open.</string> + <!-- Message shown when face authentication fails and the pin pad is visible. [CHAR LIMIT=60] --> <string name="keyguard_retry">Swipe up to try again</string> @@ -888,6 +901,17 @@ <!-- Notification when resuming an existing guest session: Action that continues with the current session [CHAR LIMIT=35] --> <string name="guest_wipe_session_dontwipe">Yes, continue</string> + <!-- App name of the notification when guest mode is entered [CHAR LIMIT=35] --> + <string name="guest_notification_app_name">Guest mode</string> + <!-- Title of the notification when guest mode is entered [CHAR LIMIT=35] --> + <string name="guest_notification_session_active">You are in guest mode</string> + + <!-- Additional message for add user confirmation dialog that is appended when current user is + guest and guest is ephemeral. This is to warn users that current guest session + would get removed after a new user is added and switched to [CHAR LIMIT=none] --> + <string name="user_add_user_message_guest_remove">\n\nAdding a new user will exit guest mode + and delete all apps and data from the current guest session.</string> + <!-- Title for the dialog that lets users know that the maximum allowed number of users on the device has been reached. [CHAR LIMIT=35]--> <string name="user_limit_reached_title">User limit reached</string> @@ -2268,8 +2292,6 @@ <string name="media_output_dialog_launch_app_text">To cast this session, please open the app.</string> <!-- App name when can't get app name [CHAR LIMIT=60] --> <string name="media_output_dialog_unknown_launch_app_name">Unknown app</string> - <!-- Button text for stopping casting [CHAR LIMIT=60] --> - <string name="media_output_dialog_button_stop_casting">Stop casting</string> <!-- Media Output Broadcast Dialog --> <!-- Title for Broadcast First Notify Dialog [CHAR LIMIT=60] --> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index c93c0652a070..04f6b06b2840 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -486,7 +486,7 @@ <style name="MediaOutputItemInactiveTitle"> <item name="android:textSize">16sp</item> - <item name="android:textColor">@color/media_dialog_item_main_content</item> + <item name="android:textColor">@color/media_dialog_inactive_item_main_content</item> </style> <style name="TunerSettings" parent="@android:style/Theme.DeviceDefault.Settings"> diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java index 618d2d2f213a..76a09b38036c 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java @@ -137,6 +137,8 @@ public class RemoteAnimationAdapterCompat { float displayH = 0; for (int i = info.getChanges().size() - 1; i >= 0; --i) { final TransitionInfo.Change change = info.getChanges().get(i); + // skip changes that we didn't wrap + if (!leashMap.containsKey(change.getLeash())) continue; if (change.getTaskInfo() != null && change.getTaskInfo().getActivityType() == ACTIVITY_TYPE_HOME) { isReturnToHome = change.getMode() == TRANSIT_OPEN @@ -173,6 +175,8 @@ public class RemoteAnimationAdapterCompat { for (int i = info.getChanges().size() - 1; i >= 0; --i) { final TransitionInfo.Change change = info.getChanges().get(i); final SurfaceControl leash = leashMap.get(change.getLeash()); + // skip changes that we didn't wrap + if (leash == null) continue; final int mode = info.getChanges().get(i).getMode(); // Only deal with independent layers if (!TransitionInfo.isIndependent(change, info)) continue; diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java index 9cf482fdf790..4ce110bf7c47 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java @@ -17,7 +17,6 @@ package com.android.systemui.shared.system; import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE; -import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_CLOSE; import static android.view.WindowManager.TRANSIT_OPEN; import static android.view.WindowManager.TRANSIT_TO_BACK; @@ -32,7 +31,6 @@ import android.app.WindowConfiguration; import android.graphics.Point; import android.graphics.Rect; import android.util.ArrayMap; -import android.util.IntArray; import android.util.SparseArray; import android.view.RemoteAnimationTarget; import android.view.SurfaceControl; @@ -142,21 +140,10 @@ public class RemoteAnimationTargetCompat { // changes should be ordered top-to-bottom in z final int mode = change.getMode(); - // Don't move anything that isn't independent within its parents - if (!TransitionInfo.isIndependent(change, info)) { - if (mode == TRANSIT_OPEN || mode == TRANSIT_TO_FRONT || mode == TRANSIT_CHANGE) { - t.setPosition(leash, change.getEndRelOffset().x, change.getEndRelOffset().y); - } - return; - } - - final boolean hasParent = change.getParent() != null; + t.reparent(leash, info.getRootLeash()); + t.setPosition(leash, change.getStartAbsBounds().left - info.getRootOffset().x, + change.getStartAbsBounds().top - info.getRootOffset().y); - if (!hasParent) { - t.reparent(leash, info.getRootLeash()); - t.setPosition(leash, change.getStartAbsBounds().left - info.getRootOffset().x, - change.getStartAbsBounds().top - info.getRootOffset().y); - } // Put all the OPEN/SHOW on top if (mode == TRANSIT_OPEN || mode == TRANSIT_TO_FRONT) { if (isOpening) { @@ -196,8 +183,7 @@ public class RemoteAnimationTargetCompat { .setContainerLayer() // Initial the surface visible to respect the visibility of the original surface. .setHidden(false) - .setParent(change.getParent() == null ? info.getRootLeash() - : info.getChange(change.getParent()).getLeash()) + .setParent(info.getRootLeash()) .build(); // Copied Transitions setup code (which expects bottom-to-top order, so we swap here) setupLeash(leashSurface, change, info.getChanges().size() - order, info, t); @@ -269,58 +255,32 @@ public class RemoteAnimationTargetCompat { public static RemoteAnimationTargetCompat[] wrap(TransitionInfo info, boolean wallpapers, SurfaceControl.Transaction t, ArrayMap<SurfaceControl, SurfaceControl> leashMap) { final ArrayList<RemoteAnimationTargetCompat> out = new ArrayList<>(); - final SparseArray<RemoteAnimationTargetCompat> childTaskTargets = new SparseArray<>(); - final IntArray excludedParentTaskIds = new IntArray(); + final SparseArray<TransitionInfo.Change> childTaskTargets = new SparseArray<>(); for (int i = 0; i < info.getChanges().size(); i++) { final TransitionInfo.Change change = info.getChanges().get(i); final boolean changeIsWallpaper = (change.getFlags() & TransitionInfo.FLAG_IS_WALLPAPER) != 0; if (wallpapers != changeIsWallpaper) continue; - final RemoteAnimationTargetCompat targetCompat = - new RemoteAnimationTargetCompat(change, info.getChanges().size() - i, info, t); - if (leashMap != null) { - leashMap.put(change.getLeash(), targetCompat.leash); - } - final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo(); - if (taskInfo != null) { - // Skip wrapping excluded parent task animate target since it will animate its child - // tasks instead. - if (excludedParentTaskIds.binarySearch(taskInfo.taskId) != -1) { - continue; - } - - // Check if there's a matching child task target in cache. - RemoteAnimationTargetCompat childTaskTarget = childTaskTargets.get(taskInfo.taskId); - if (childTaskTarget != null) { - // Launcher monitors leaf task ids to perform animation, override the target - // with its child task information so Launcher can animate this parent surface - // directly with leaf task information. - targetCompat.taskInfo = childTaskTarget.taskInfo; - targetCompat.taskId = childTaskTarget.taskId; - childTaskTargets.remove(taskInfo.taskId); - } - - // Check if it has a parent task, cache its information for later use. - if (taskInfo.parentTaskId != -1 - && excludedParentTaskIds.binarySearch(taskInfo.parentTaskId) == -1) { - if (!childTaskTargets.contains(taskInfo.parentTaskId)) { - // Cache the target amd skip wrapping it info the final animation targets. - // Otherwise, the child task might get transformed multiple-times with the - // flow like RecentsView#redrawLiveTile. - childTaskTargets.put(taskInfo.parentTaskId, targetCompat); + if (!wallpapers) { + final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo(); + // Children always come before parent since changes are in top-to-bottom z-order. + if (taskInfo != null) { + if (childTaskTargets.contains(taskInfo.taskId)) { + // has children, so not a leaf. Skip. continue; } - - // There is another child task target cached with the same parent task id. - // Which means the parent having multiple child tasks in transition. Stop - // propagate child task info. - childTaskTarget = childTaskTargets.removeReturnOld(taskInfo.parentTaskId); - out.add(childTaskTarget); - excludedParentTaskIds.add(taskInfo.parentTaskId); + if (taskInfo.hasParentTask()) { + childTaskTargets.put(taskInfo.parentTaskId, change); + } } } + final RemoteAnimationTargetCompat targetCompat = + new RemoteAnimationTargetCompat(change, info.getChanges().size() - i, info, t); + if (leashMap != null) { + leashMap.put(change.getLeash(), targetCompat.leash); + } out.add(targetCompat); } diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java index de35514be2cb..ef93bc311072 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java @@ -27,6 +27,7 @@ import static android.view.WindowManager.TRANSIT_TO_FRONT; import static android.window.TransitionFilter.CONTAINER_ORDER_TOP; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_RECENTS; +import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING; import android.annotation.NonNull; import android.annotation.Nullable; @@ -132,16 +133,17 @@ public class RemoteTransitionCompat implements Parcelable { // TODO(b/177438007): Move this set-up logic into launcher's animation impl. mToken = transition; // This transition is for opening recents, so recents is on-top. We want to draw - // the current going-away task on top of recents, though, so move it to front + // the current going-away tasks on top of recents, though, so move them to front. + // Note that we divide up the "layer space" into 3 regions each the size of + // the change count. This way we can easily move changes into above/below/between + // while maintaining their relative ordering. final ArrayList<WindowContainerToken> pausingTasks = new ArrayList<>(); WindowContainerToken pipTask = null; WindowContainerToken recentsTask = null; - for (int i = info.getChanges().size() - 1; i >= 0; --i) { - final TransitionInfo.Change change = info.getChanges().get(i); - final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo(); - if (change.getMode() == TRANSIT_CLOSE || change.getMode() == TRANSIT_TO_BACK) { - t.setLayer(leashMap.get(change.getLeash()), - info.getChanges().size() * 3 - i); + for (int i = apps.length - 1; i >= 0; --i) { + final ActivityManager.RunningTaskInfo taskInfo = apps[i].taskInfo; + if (apps[i].mode == MODE_CLOSING) { + t.setLayer(apps[i].leash, info.getChanges().size() * 3 - i); if (taskInfo == null) { continue; } @@ -154,8 +156,7 @@ public class RemoteTransitionCompat implements Parcelable { } else if (taskInfo != null && taskInfo.topActivityType == ACTIVITY_TYPE_RECENTS) { // This task is for recents, keep it on top. - t.setLayer(leashMap.get(change.getLeash()), - info.getChanges().size() * 3 - i); + t.setLayer(apps[i].leash, info.getChanges().size() * 3 - i); recentsTask = taskInfo.token; } else if (taskInfo != null && taskInfo.topActivityType == ACTIVITY_TYPE_HOME) { recentsTask = taskInfo.token; @@ -387,12 +388,17 @@ public class RemoteTransitionCompat implements Parcelable { wct.restoreTransientOrder(mRecentsTask); } } else { - if (!sendUserLeaveHint) { - for (int i = 0; i < mPausingTasks.size(); ++i) { + for (int i = 0; i < mPausingTasks.size(); ++i) { + if (!sendUserLeaveHint) { // This means recents is not *actually* finishing, so of course we gotta // do special stuff in WMCore to accommodate. wct.setDoNotPip(mPausingTasks.get(i)); } + // Since we will reparent out of the leashes, pre-emptively hide the child + // surface to match the leash. Otherwise, there will be a flicker before the + // visibility gets committed in Core when using split-screen (in splitscreen, + // the leaf-tasks are not "independent" so aren't hidden by normal setup). + t.hide(mInfo.getChange(mPausingTasks.get(i)).getLeash()); } if (mPipTask != null && mPipTransaction != null && sendUserLeaveHint) { t.show(mInfo.getChange(mPipTask).getLeash()); diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/tracing/FrameProtoTracer.java b/packages/SystemUI/shared/src/com/android/systemui/shared/tracing/FrameProtoTracer.java index 4394ecbf79eb..98212e1d91b6 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/tracing/FrameProtoTracer.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/tracing/FrameProtoTracer.java @@ -25,8 +25,8 @@ import com.android.internal.util.TraceBuffer; import java.io.File; import java.io.IOException; import java.io.OutputStream; +import java.util.ArrayDeque; import java.util.ArrayList; -import java.util.LinkedList; import java.util.Queue; import java.util.function.Consumer; @@ -50,7 +50,7 @@ public class FrameProtoTracer<P, S extends P, T extends P, R> private final File mTraceFile; private final ProtoTraceParams<P, S, T, R> mParams; private Choreographer mChoreographer; - private final Queue<T> mPool = new LinkedList<>(); + private final Queue<T> mPool = new ArrayDeque<>(); private final ArrayList<ProtoTraceable<R>> mTraceables = new ArrayList<>(); private final ArrayList<ProtoTraceable<R>> mTmpTraceables = new ArrayList<>(); diff --git a/packages/SystemUI/src/com/android/keyguard/AnimatableClockView.kt b/packages/SystemUI/src/com/android/keyguard/AnimatableClockView.kt index 19d39d515325..d44598049806 100644 --- a/packages/SystemUI/src/com/android/keyguard/AnimatableClockView.kt +++ b/packages/SystemUI/src/com/android/keyguard/AnimatableClockView.kt @@ -284,6 +284,8 @@ class AnimatableClockView @JvmOverloads constructor( ) } + private val glyphFilter: GlyphCallback? = null // Add text animation tweak here. + /** * Set text style with an optional animation. * @@ -315,6 +317,7 @@ class AnimatableClockView @JvmOverloads constructor( delay = delay, onAnimationEnd = onAnimationEnd ) + textAnimator?.glyphFilter = glyphFilter } else { // when the text animator is set, update its start values onTextAnimatorInitialized = Runnable { @@ -328,6 +331,7 @@ class AnimatableClockView @JvmOverloads constructor( delay = delay, onAnimationEnd = onAnimationEnd ) + textAnimator?.glyphFilter = glyphFilter } } } diff --git a/packages/SystemUI/src/com/android/keyguard/TextAnimator.kt b/packages/SystemUI/src/com/android/keyguard/TextAnimator.kt index 336101528450..ade89af81bd7 100644 --- a/packages/SystemUI/src/com/android/keyguard/TextAnimator.kt +++ b/packages/SystemUI/src/com/android/keyguard/TextAnimator.kt @@ -22,12 +22,14 @@ import android.animation.TimeInterpolator import android.animation.ValueAnimator import android.graphics.Canvas import android.graphics.Typeface +import android.graphics.fonts.Font import android.text.Layout import android.util.SparseArray private const val TAG_WGHT = "wght" private const val DEFAULT_ANIMATION_DURATION: Long = 300 +typealias GlyphCallback = (TextAnimator.PositionedGlyph, Float) -> Unit /** * This class provides text animation between two styles. * @@ -74,6 +76,59 @@ class TextAnimator( }) } + sealed class PositionedGlyph { + + /** + * Mutable X coordinate of the glyph position relative from drawing offset. + */ + var x: Float = 0f + + /** + * Mutable Y coordinate of the glyph position relative from the baseline. + */ + var y: Float = 0f + + /** + * Mutable text size of the glyph in pixels. + */ + var textSize: Float = 0f + + /** + * Mutable color of the glyph. + */ + var color: Int = 0 + + /** + * Immutable character offset in the text that the current font run start. + */ + abstract var runStart: Int + protected set + + /** + * Immutable run length of the font run. + */ + abstract var runLength: Int + protected set + + /** + * Immutable glyph index of the font run. + */ + abstract var glyphIndex: Int + protected set + + /** + * Immutable font instance for this font run. + */ + abstract var font: Font + protected set + + /** + * Immutable glyph ID for this glyph. + */ + abstract var glyphId: Int + protected set + } + private val typefaceCache = SparseArray<Typeface?>() fun updateLayout(layout: Layout) { @@ -84,6 +139,57 @@ class TextAnimator( return animator.isRunning } + /** + * GlyphFilter applied just before drawing to canvas for tweaking positions and text size. + * + * This callback is called for each glyphs just before drawing the glyphs. This function will + * be called with the intrinsic position, size, color, glyph ID and font instance. You can + * mutate the position, size and color for tweaking animations. + * Do not keep the reference of passed glyph object. The interpolator reuses that object for + * avoiding object allocations. + * + * Details: + * The text is drawn with font run units. The font run is a text segment that draws with the + * same font. The {@code runStart} and {@code runLimit} is a range of the font run in the text + * that current glyph is in. Once the font run is determined, the system will convert characters + * into glyph IDs. The {@code glyphId} is the glyph identifier in the font and + * {@code glyphIndex} is the offset of the converted glyph array. Please note that the + * {@code glyphIndex} is not a character index, because the character will not be converted to + * glyph one-by-one. If there are ligatures including emoji sequence, etc, the glyph ID may be + * composed from multiple characters. + * + * Here is an example of font runs: "fin. 終わり" + * + * Characters : f i n . _ 終 わ り + * Code Points: \u0066 \u0069 \u006E \u002E \u0020 \u7D42 \u308F \u308A + * Font Runs : <-- Roboto-Regular.ttf --><-- NotoSans-CJK.otf --> + * runStart = 0, runLength = 5 runStart = 5, runLength = 3 + * Glyph IDs : 194 48 7 8 4367 1039 1002 + * Glyph Index: 0 1 2 3 0 1 2 + * + * In this example, the "fi" is converted into ligature form, thus the single glyph ID is + * assigned for two characters, f and i. + * + * Example: + * ``` + * private val glyphFilter: GlyphCallback = { glyph, progress -> + * val index = glyph.runStart + * val i = glyph.glyphIndex + * val moveAmount = 1.3f + * val sign = (-1 + 2 * ((i + index) % 2)) + * val turnProgress = if (progress < .5f) progress / 0.5f else (1.0f - progress) / 0.5f + * + * // You can modify (x, y) coordinates, textSize and color during animation. + * glyph.textSize += glyph.textSize * sign * moveAmount * turnProgress + * glyph.y += glyph.y * sign * moveAmount * turnProgress + * glyph.x += glyph.x * sign * moveAmount * turnProgress + * } + * ``` + */ + var glyphFilter: GlyphCallback? + get() = textInterpolator.glyphFilter + set(value) { textInterpolator.glyphFilter = value } + fun draw(c: Canvas) = textInterpolator.draw(c) /** diff --git a/packages/SystemUI/src/com/android/keyguard/TextInterpolator.kt b/packages/SystemUI/src/com/android/keyguard/TextInterpolator.kt index 5d5797cbbb3d..20dbe29efb35 100644 --- a/packages/SystemUI/src/com/android/keyguard/TextInterpolator.kt +++ b/packages/SystemUI/src/com/android/keyguard/TextInterpolator.kt @@ -89,8 +89,11 @@ class TextInterpolator( private var lines = listOf<Line>() private val fontInterpolator = FontInterpolator() - // Recycling object for glyph drawing. Will be extended for the longest font run if needed. - private val tmpDrawPaint = TextPaint() + // Recycling object for glyph drawing and tweaking. + private val tmpPaint = TextPaint() + private val tmpPaintForGlyph by lazy { TextPaint() } + private val tmpGlyph by lazy { MutablePositionedGlyph() } + // Will be extended for the longest font run if needed. private var tmpPositionArray = FloatArray(20) /** @@ -206,8 +209,8 @@ class TextInterpolator( } else if (progress == 1f) { basePaint.set(targetPaint) } else { - lerp(basePaint, targetPaint, progress, tmpDrawPaint) - basePaint.set(tmpDrawPaint) + lerp(basePaint, targetPaint, progress, tmpPaint) + basePaint.set(tmpPaint) } lines.forEach { line -> @@ -231,7 +234,7 @@ class TextInterpolator( * @param canvas a canvas. */ fun draw(canvas: Canvas) { - lerp(basePaint, targetPaint, progress, tmpDrawPaint) + lerp(basePaint, targetPaint, progress, tmpPaint) lines.forEachIndexed { lineNo, line -> line.runs.forEach { run -> canvas.save() @@ -241,7 +244,7 @@ class TextInterpolator( canvas.translate(origin, layout.getLineBaseline(lineNo).toFloat()) run.fontRuns.forEach { fontRun -> - drawFontRun(canvas, run, fontRun, tmpDrawPaint) + drawFontRun(canvas, run, fontRun, tmpPaint) } } finally { canvas.restore() @@ -330,24 +333,82 @@ class TextInterpolator( } } + private class MutablePositionedGlyph : TextAnimator.PositionedGlyph() { + override var runStart: Int = 0 + public set + override var runLength: Int = 0 + public set + override var glyphIndex: Int = 0 + public set + override lateinit var font: Font + public set + override var glyphId: Int = 0 + public set + } + + var glyphFilter: GlyphCallback? = null + // Draws single font run. private fun drawFontRun(c: Canvas, line: Run, run: FontRun, paint: Paint) { var arrayIndex = 0 + val font = fontInterpolator.lerp(run.baseFont, run.targetFont, progress) + + val glyphFilter = glyphFilter + if (glyphFilter == null) { + for (i in run.start until run.end) { + tmpPositionArray[arrayIndex++] = + MathUtils.lerp(line.baseX[i], line.targetX[i], progress) + tmpPositionArray[arrayIndex++] = + MathUtils.lerp(line.baseY[i], line.targetY[i], progress) + } + c.drawGlyphs(line.glyphIds, run.start, tmpPositionArray, 0, run.length, font, paint) + return + } + + tmpGlyph.font = font + tmpGlyph.runStart = run.start + tmpGlyph.runLength = run.end - run.start + + tmpPaintForGlyph.set(paint) + var prevStart = run.start + for (i in run.start until run.end) { - tmpPositionArray[arrayIndex++] = - MathUtils.lerp(line.baseX[i], line.targetX[i], progress) - tmpPositionArray[arrayIndex++] = - MathUtils.lerp(line.baseY[i], line.targetY[i], progress) + tmpGlyph.glyphId = line.glyphIds[i] + tmpGlyph.x = MathUtils.lerp(line.baseX[i], line.targetX[i], progress) + tmpGlyph.y = MathUtils.lerp(line.baseY[i], line.targetY[i], progress) + tmpGlyph.textSize = paint.textSize + tmpGlyph.color = paint.color + + glyphFilter(tmpGlyph, progress) + + if (tmpGlyph.textSize != paint.textSize || tmpGlyph.color != paint.color) { + tmpPaintForGlyph.textSize = tmpGlyph.textSize + tmpPaintForGlyph.color = tmpGlyph.color + + c.drawGlyphs( + line.glyphIds, + prevStart, + tmpPositionArray, + 0, + i - prevStart, + font, + tmpPaintForGlyph) + prevStart = i + arrayIndex = 0 + } + + tmpPositionArray[arrayIndex++] = tmpGlyph.x + tmpPositionArray[arrayIndex++] = tmpGlyph.y } c.drawGlyphs( line.glyphIds, - run.start, + prevStart, tmpPositionArray, 0, - run.length, - fontInterpolator.lerp(run.baseFont, run.targetFont, progress), - paint) + run.end - prevStart, + font, + tmpPaintForGlyph) } private fun updatePositionsAndFonts( diff --git a/packages/SystemUI/src/com/android/systemui/GuestResetOrExitSessionReceiver.java b/packages/SystemUI/src/com/android/systemui/GuestResetOrExitSessionReceiver.java new file mode 100644 index 000000000000..fd84543ee50b --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/GuestResetOrExitSessionReceiver.java @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui; + +import android.annotation.SdkConstant; +import android.annotation.SdkConstant.SdkConstantType; +import android.app.AlertDialog; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.UserInfo; +import android.os.UserHandle; + +import com.android.internal.logging.UiEventLogger; +import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.qs.QSUserSwitcherEvent; +import com.android.systemui.settings.UserTracker; +import com.android.systemui.statusbar.phone.SystemUIDialog; +import com.android.systemui.statusbar.policy.UserSwitcherController; + +import javax.inject.Inject; + +import dagger.assisted.Assisted; +import dagger.assisted.AssistedFactory; +import dagger.assisted.AssistedInject; + +/** + * Manages handling of guest session persistent notification + * and actions to reset guest or exit guest session + */ +public final class GuestResetOrExitSessionReceiver extends BroadcastReceiver { + + private static final String TAG = GuestResetOrExitSessionReceiver.class.getSimpleName(); + + /** + * Broadcast sent to the system when guest user needs to be reset. + * This is only sent to registered receivers, not manifest receivers. + * + * @hide + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_GUEST_RESET = "android.intent.action.GUEST_RESET"; + + /** + * Broadcast sent to the system when guest user needs to exit. + * This is only sent to registered receivers, not manifest receivers. + * + * @hide + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_GUEST_EXIT = "android.intent.action.GUEST_EXIT"; + + public AlertDialog mExitSessionDialog; + public AlertDialog mResetSessionDialog; + private final UserTracker mUserTracker; + private final BroadcastDispatcher mBroadcastDispatcher; + private final ResetSessionDialog.Factory mResetSessionDialogFactory; + private final ExitSessionDialog.Factory mExitSessionDialogFactory; + + @Inject + public GuestResetOrExitSessionReceiver(UserTracker userTracker, + BroadcastDispatcher broadcastDispatcher, + ResetSessionDialog.Factory resetSessionDialogFactory, + ExitSessionDialog.Factory exitSessionDialogFactory) { + mUserTracker = userTracker; + mBroadcastDispatcher = broadcastDispatcher; + mResetSessionDialogFactory = resetSessionDialogFactory; + mExitSessionDialogFactory = exitSessionDialogFactory; + } + + /** + * Register this receiver with the {@link BroadcastDispatcher} + */ + public void register() { + IntentFilter intentFilter = new IntentFilter(); + intentFilter.addAction(ACTION_GUEST_RESET); + intentFilter.addAction(ACTION_GUEST_EXIT); + mBroadcastDispatcher.registerReceiver(this, intentFilter, null /* handler */, + UserHandle.SYSTEM); + } + + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + + cancelResetDialog(); + cancelExitDialog(); + + UserInfo currentUser = mUserTracker.getUserInfo(); + if (!currentUser.isGuest()) { + return; + } + + if (ACTION_GUEST_RESET.equals(action)) { + mResetSessionDialog = mResetSessionDialogFactory.create(currentUser.id); + mResetSessionDialog.show(); + } else if (ACTION_GUEST_EXIT.equals(action)) { + mExitSessionDialog = mExitSessionDialogFactory.create(currentUser.id, + currentUser.isEphemeral()); + mExitSessionDialog.show(); + } + } + + private void cancelResetDialog() { + if (mResetSessionDialog != null && mResetSessionDialog.isShowing()) { + mResetSessionDialog.cancel(); + mResetSessionDialog = null; + } + } + + private void cancelExitDialog() { + if (mExitSessionDialog != null && mExitSessionDialog.isShowing()) { + mExitSessionDialog.cancel(); + mExitSessionDialog = null; + } + } + + /** + * Dialog shown when asking for confirmation before + * reset and restart of guest user. + */ + public static final class ResetSessionDialog extends SystemUIDialog implements + DialogInterface.OnClickListener { + + private final UserSwitcherController mUserSwitcherController; + private final UiEventLogger mUiEventLogger; + private final int mUserId; + + /** Factory class to create guest reset dialog instance */ + @AssistedFactory + public interface Factory { + /** Create a guest reset dialog instance */ + ResetSessionDialog create(int userId); + } + + @AssistedInject + ResetSessionDialog(Context context, + UserSwitcherController userSwitcherController, + UiEventLogger uiEventLogger, + @Assisted int userId) { + super(context); + + setTitle(com.android.settingslib.R.string.guest_reset_and_restart_dialog_title); + setMessage(context.getString( + com.android.settingslib.R.string.guest_reset_and_restart_dialog_message)); + setButton(DialogInterface.BUTTON_NEUTRAL, + context.getString(android.R.string.cancel), this); + setButton(DialogInterface.BUTTON_POSITIVE, + context.getString( + com.android.settingslib.R.string.guest_reset_guest_confirm_button), this); + setCanceledOnTouchOutside(false); + + mUserSwitcherController = userSwitcherController; + mUiEventLogger = uiEventLogger; + mUserId = userId; + } + + @Override + public void onClick(DialogInterface dialog, int which) { + if (which == DialogInterface.BUTTON_POSITIVE) { + mUiEventLogger.log(QSUserSwitcherEvent.QS_USER_GUEST_REMOVE); + mUserSwitcherController.removeGuestUser(mUserId, UserHandle.USER_NULL); + } else if (which == DialogInterface.BUTTON_NEUTRAL) { + cancel(); + } + } + } + + /** + * Dialog shown when asking for confirmation before + * exit of guest user. + */ + public static final class ExitSessionDialog extends SystemUIDialog implements + DialogInterface.OnClickListener { + + private final UserSwitcherController mUserSwitcherController; + private final int mUserId; + private boolean mIsEphemeral; + + /** Factory class to create guest exit dialog instance */ + @AssistedFactory + public interface Factory { + /** Create a guest exit dialog instance */ + ExitSessionDialog create(int userId, boolean isEphemeral); + } + + @AssistedInject + ExitSessionDialog(Context context, + UserSwitcherController userSwitcherController, + @Assisted int userId, + @Assisted boolean isEphemeral) { + super(context); + + if (isEphemeral) { + setTitle(context.getString( + com.android.settingslib.R.string.guest_exit_dialog_title)); + setMessage(context.getString( + com.android.settingslib.R.string.guest_exit_dialog_message)); + setButton(DialogInterface.BUTTON_NEUTRAL, + context.getString(android.R.string.cancel), this); + setButton(DialogInterface.BUTTON_POSITIVE, + context.getString( + com.android.settingslib.R.string.guest_exit_dialog_button), this); + } else { + setTitle(context.getString( + com.android.settingslib + .R.string.guest_exit_dialog_title_non_ephemeral)); + setMessage(context.getString( + com.android.settingslib + .R.string.guest_exit_dialog_message_non_ephemeral)); + setButton(DialogInterface.BUTTON_NEUTRAL, + context.getString(android.R.string.cancel), this); + setButton(DialogInterface.BUTTON_NEGATIVE, + context.getString( + com.android.settingslib.R.string.guest_exit_clear_data_button), this); + setButton(DialogInterface.BUTTON_POSITIVE, + context.getString( + com.android.settingslib.R.string.guest_exit_save_data_button), this); + } + setCanceledOnTouchOutside(false); + + mUserSwitcherController = userSwitcherController; + mUserId = userId; + mIsEphemeral = isEphemeral; + } + + @Override + public void onClick(DialogInterface dialog, int which) { + if (mIsEphemeral) { + if (which == DialogInterface.BUTTON_POSITIVE) { + // Ephemeral guest: exit guest, guest is removed by the system + // on exit, since its marked ephemeral + mUserSwitcherController.exitGuestUser(mUserId, UserHandle.USER_NULL, false); + } else if (which == DialogInterface.BUTTON_NEUTRAL) { + // Cancel clicked, do nothing + cancel(); + } + } else { + if (which == DialogInterface.BUTTON_POSITIVE) { + // Non-ephemeral guest: exit guest, guest is not removed by the system + // on exit, since its marked non-ephemeral + mUserSwitcherController.exitGuestUser(mUserId, UserHandle.USER_NULL, false); + } else if (which == DialogInterface.BUTTON_NEGATIVE) { + // Non-ephemeral guest: remove guest and then exit + mUserSwitcherController.exitGuestUser(mUserId, UserHandle.USER_NULL, true); + } else if (which == DialogInterface.BUTTON_NEUTRAL) { + // Cancel clicked, do nothing + cancel(); + } + } + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/GuestResumeSessionReceiver.java b/packages/SystemUI/src/com/android/systemui/GuestResumeSessionReceiver.java index 9a6020f8556b..76a7cad15419 100644 --- a/packages/SystemUI/src/com/android/systemui/GuestResumeSessionReceiver.java +++ b/packages/SystemUI/src/com/android/systemui/GuestResumeSessionReceiver.java @@ -35,12 +35,18 @@ import com.android.systemui.statusbar.phone.SystemUIDialog; import com.android.systemui.statusbar.policy.UserSwitcherController; import com.android.systemui.util.settings.SecureSettings; +import javax.inject.Inject; + +import dagger.assisted.Assisted; +import dagger.assisted.AssistedFactory; +import dagger.assisted.AssistedInject; + /** * Manages notification when a guest session is resumed. */ public class GuestResumeSessionReceiver extends BroadcastReceiver { - private static final String TAG = "GuestResumeSessionReceiver"; + private static final String TAG = GuestResumeSessionReceiver.class.getSimpleName(); @VisibleForTesting public static final String SETTING_GUEST_HAS_LOGGED_IN = "systemui.guest_has_logged_in"; @@ -48,27 +54,31 @@ public class GuestResumeSessionReceiver extends BroadcastReceiver { @VisibleForTesting public AlertDialog mNewSessionDialog; private final UserTracker mUserTracker; - private final UserSwitcherController mUserSwitcherController; - private final UiEventLogger mUiEventLogger; private final SecureSettings mSecureSettings; - - public GuestResumeSessionReceiver(UserSwitcherController userSwitcherController, - UserTracker userTracker, UiEventLogger uiEventLogger, - SecureSettings secureSettings) { - mUserSwitcherController = userSwitcherController; + private final BroadcastDispatcher mBroadcastDispatcher; + private final ResetSessionDialog.Factory mResetSessionDialogFactory; + private final GuestSessionNotification mGuestSessionNotification; + + @Inject + public GuestResumeSessionReceiver( + UserTracker userTracker, + SecureSettings secureSettings, + BroadcastDispatcher broadcastDispatcher, + GuestSessionNotification guestSessionNotification, + ResetSessionDialog.Factory resetSessionDialogFactory) { mUserTracker = userTracker; - mUiEventLogger = uiEventLogger; mSecureSettings = secureSettings; + mBroadcastDispatcher = broadcastDispatcher; + mGuestSessionNotification = guestSessionNotification; + mResetSessionDialogFactory = resetSessionDialogFactory; } /** * Register this receiver with the {@link BroadcastDispatcher} - * - * @param broadcastDispatcher to register the receiver. */ - public void register(BroadcastDispatcher broadcastDispatcher) { + public void register() { IntentFilter f = new IntentFilter(Intent.ACTION_USER_SWITCHED); - broadcastDispatcher.registerReceiver(this, f, null /* handler */, UserHandle.SYSTEM); + mBroadcastDispatcher.registerReceiver(this, f, null /* handler */, UserHandle.SYSTEM); } @Override @@ -89,14 +99,25 @@ public class GuestResumeSessionReceiver extends BroadcastReceiver { return; } - int notFirstLogin = mSecureSettings.getIntForUser( + int guestLoginState = mSecureSettings.getIntForUser( SETTING_GUEST_HAS_LOGGED_IN, 0, userId); - if (notFirstLogin != 0) { - mNewSessionDialog = new ResetSessionDialog(context, mUserSwitcherController, - mUiEventLogger, userId); + + if (guestLoginState == 0) { + // set 1 to indicate, 1st login + guestLoginState = 1; + mSecureSettings.putIntForUser(SETTING_GUEST_HAS_LOGGED_IN, guestLoginState, userId); + } else if (guestLoginState == 1) { + // set 2 to indicate, 2nd or later login + guestLoginState = 2; + mSecureSettings.putIntForUser(SETTING_GUEST_HAS_LOGGED_IN, guestLoginState, userId); + } + + mGuestSessionNotification.createPersistentNotification(currentUser, + (guestLoginState <= 1)); + + if (guestLoginState > 1) { + mNewSessionDialog = mResetSessionDialogFactory.create(userId); mNewSessionDialog.show(); - } else { - mSecureSettings.putIntForUser(SETTING_GUEST_HAS_LOGGED_IN, 1, userId); } } } @@ -124,10 +145,19 @@ public class GuestResumeSessionReceiver extends BroadcastReceiver { private final UiEventLogger mUiEventLogger; private final int mUserId; - ResetSessionDialog(Context context, + + /** Factory class to create guest reset dialog instance */ + @AssistedFactory + public interface Factory { + /** Create a guest reset dialog instance */ + ResetSessionDialog create(int userId); + } + + @AssistedInject + public ResetSessionDialog(Context context, UserSwitcherController userSwitcherController, UiEventLogger uiEventLogger, - int userId) { + @Assisted int userId) { super(context, false /* dismissOnDeviceLock */); setTitle(context.getString(R.string.guest_wipe_session_title)); diff --git a/packages/SystemUI/src/com/android/systemui/GuestSessionNotification.java b/packages/SystemUI/src/com/android/systemui/GuestSessionNotification.java new file mode 100644 index 000000000000..b0eaab97c5ac --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/GuestSessionNotification.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui; + +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.content.pm.UserInfo; +import android.os.Bundle; +import android.os.UserHandle; +import android.provider.Settings; +import android.util.FeatureFlagUtils; + +import com.android.internal.messages.nano.SystemMessageProto; +import com.android.systemui.util.NotificationChannels; + +import javax.inject.Inject; + +/** + * Posts a persistent notification on entry to guest mode + */ +public final class GuestSessionNotification { + + private static final String TAG = GuestSessionNotification.class.getSimpleName(); + + private final Context mContext; + private final NotificationManager mNotificationManager; + + @Inject + public GuestSessionNotification(Context context, + NotificationManager notificationManager) { + mContext = context; + mNotificationManager = notificationManager; + } + + private void overrideNotificationAppName(Notification.Builder notificationBuilder) { + final Bundle extras = new Bundle(); + String appName = mContext.getString(R.string.guest_notification_app_name); + + extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, appName); + + notificationBuilder.addExtras(extras); + } + + void createPersistentNotification(UserInfo userInfo, boolean isGuestFirstLogin) { + if (!FeatureFlagUtils.isEnabled(mContext, + FeatureFlagUtils.SETTINGS_GUEST_MODE_UX_CHANGES) + || !userInfo.isGuest()) { + // we create a persistent notification only if enabled and only for guests + return; + } + String contentText; + if (userInfo.isEphemeral()) { + contentText = mContext.getString(R.string.guest_notification_ephemeral); + } else if (isGuestFirstLogin) { + contentText = mContext.getString(R.string.guest_notification_non_ephemeral); + } else { + contentText = mContext.getString( + R.string.guest_notification_non_ephemeral_non_first_login); + } + + final Intent guestExitIntent = new Intent( + GuestResetOrExitSessionReceiver.ACTION_GUEST_EXIT); + final Intent userSettingsIntent = new Intent(Settings.ACTION_USER_SETTINGS); + + PendingIntent guestExitPendingIntent = + PendingIntent.getBroadcastAsUser(mContext, 0, guestExitIntent, + PendingIntent.FLAG_IMMUTABLE, + UserHandle.SYSTEM); + + PendingIntent userSettingsPendingIntent = + PendingIntent.getActivityAsUser(mContext, 0, userSettingsIntent, + PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE, + null, + UserHandle.of(userInfo.id)); + + Notification.Builder builder = new Notification.Builder(mContext, + NotificationChannels.ALERTS) + .setSmallIcon(R.drawable.ic_account_circle) + .setContentTitle(mContext.getString(R.string.guest_notification_session_active)) + .setContentText(contentText) + .setPriority(Notification.PRIORITY_DEFAULT) + .setOngoing(true) + .setContentIntent(userSettingsPendingIntent); + + // we show reset button only if this is a 2nd or later login + if (!isGuestFirstLogin) { + final Intent guestResetIntent = new Intent( + GuestResetOrExitSessionReceiver.ACTION_GUEST_RESET); + + PendingIntent guestResetPendingIntent = + PendingIntent.getBroadcastAsUser(mContext, 0, guestResetIntent, + PendingIntent.FLAG_IMMUTABLE, + UserHandle.SYSTEM); + + builder.addAction(R.drawable.ic_sysbar_home, + mContext.getString( + com.android.settingslib.R.string.guest_reset_guest_confirm_button), + guestResetPendingIntent); + } + builder.addAction(R.drawable.ic_sysbar_home, + mContext.getString( + com.android.settingslib.R.string.guest_exit_button), + guestExitPendingIntent); + + overrideNotificationAppName(builder); + + mNotificationManager.notifyAsUser(null, + SystemMessageProto.SystemMessage.NOTE_GUEST_SESSION, + builder.build(), + UserHandle.of(userInfo.id)); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java index 8e1132600a64..d4dad73a49f2 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java @@ -149,7 +149,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba final TaskStackListener mTaskStackListener = new TaskStackListener() { @Override public void onTaskStackChanged() { - mHandler.post(AuthController.this::handleTaskStackChanged); + mHandler.post(AuthController.this::cancelIfOwnerIsNotInForeground); } }; @@ -200,7 +200,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba } }; - private void handleTaskStackChanged() { + private void cancelIfOwnerIsNotInForeground() { mExecution.assertIsMainThread(); if (mCurrentDialog != null) { try { @@ -212,7 +212,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba final String topPackage = runningTasks.get(0).topActivity.getPackageName(); if (!topPackage.contentEquals(clientPackage) && !Utils.isSystem(mContext, clientPackage)) { - Log.w(TAG, "Evicting client due to: " + topPackage); + Log.e(TAG, "Evicting client due to: " + topPackage); mCurrentDialog.dismissWithoutCallback(true /* animate */); mCurrentDialog = null; mOrientationListener.disable(); @@ -919,6 +919,10 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba mCurrentDialog = newDialog; mCurrentDialog.show(mWindowManager, savedState); mOrientationListener.enable(); + + if (!promptInfo.isAllowBackgroundAuthentication()) { + mHandler.post(this::cancelIfOwnerIsNotInForeground); + } } private void onDialogDismissed(@DismissedReason int reason) { diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java index 6156e549ffbf..e8cfd422cc8a 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java @@ -494,7 +494,7 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud public void onPanelExpansionChanged( float fraction, boolean expanded, boolean tracking) { mPanelExpansionFraction = - mKeyguardViewManager.bouncerIsInTransit() ? BouncerPanelExpansionCalculator + mKeyguardViewManager.isBouncerInTransit() ? BouncerPanelExpansionCalculator .aboutToShowBouncerProgress(fraction) : fraction; updateAlpha(); } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/TimeLimitedMotionEventBuffer.java b/packages/SystemUI/src/com/android/systemui/classifier/TimeLimitedMotionEventBuffer.java index e5da38936593..4773f2a3b13e 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/TimeLimitedMotionEventBuffer.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/TimeLimitedMotionEventBuffer.java @@ -18,9 +18,9 @@ package com.android.systemui.classifier; import android.view.MotionEvent; +import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; -import java.util.LinkedList; import java.util.List; import java.util.ListIterator; @@ -33,13 +33,13 @@ import java.util.ListIterator; */ public class TimeLimitedMotionEventBuffer implements List<MotionEvent> { - private final LinkedList<MotionEvent> mMotionEvents; + private final List<MotionEvent> mMotionEvents; private final long mMaxAgeMs; public TimeLimitedMotionEventBuffer(long maxAgeMs) { super(); mMaxAgeMs = maxAgeMs; - mMotionEvents = new LinkedList<>(); + mMotionEvents = new ArrayList<>(); } private void ejectOldEvents() { @@ -47,7 +47,7 @@ public class TimeLimitedMotionEventBuffer implements List<MotionEvent> { return; } Iterator<MotionEvent> iter = listIterator(); - long mostRecentMs = mMotionEvents.getLast().getEventTime(); + long mostRecentMs = mMotionEvents.get(mMotionEvents.size() - 1).getEventTime(); while (iter.hasNext()) { MotionEvent ev = iter.next(); if (mostRecentMs - ev.getEventTime() > mMaxAgeMs) { diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt index bed553e6e4d6..2ea596788091 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt @@ -33,6 +33,7 @@ import android.service.controls.actions.ControlAction import android.util.ArrayMap import android.util.Log import com.android.internal.annotations.VisibleForTesting +import com.android.internal.notification.NotificationAccessConfirmationActivityContract.EXTRA_USER_ID import com.android.systemui.Dumpable import com.android.systemui.backup.BackupHelper import com.android.systemui.broadcast.BroadcastDispatcher @@ -43,6 +44,7 @@ import com.android.systemui.controls.ui.ControlsUiController import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dump.DumpManager +import com.android.systemui.people.widget.PeopleSpaceWidgetProvider.EXTRA_USER_HANDLE import com.android.systemui.settings.UserTracker import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl.Companion.PREFS_CONTROLS_FILE import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl.Companion.PREFS_CONTROLS_SEEDING_COMPLETED diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt index f9115b20ca06..3eb58bba1ca4 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt @@ -343,7 +343,7 @@ private class ControlHolderAccessibilityDelegate( info.className = Switch::class.java.name } - override fun performAccessibilityAction(host: View?, action: Int, args: Bundle?): Boolean { + override fun performAccessibilityAction(host: View, action: Int, args: Bundle?): Boolean { if (super.performAccessibilityAction(host, action, args)) { return true } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java index 0cf3333d12a6..8ba6f1c4a411 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java @@ -18,6 +18,8 @@ package com.android.systemui.dagger; import android.content.BroadcastReceiver; +import com.android.systemui.GuestResetOrExitSessionReceiver; +import com.android.systemui.GuestResumeSessionReceiver; import com.android.systemui.media.dialog.MediaOutputDialogReceiver; import com.android.systemui.people.widget.PeopleSpaceWidgetPinnedReceiver; import com.android.systemui.people.widget.PeopleSpaceWidgetProvider; @@ -89,4 +91,21 @@ public abstract class DefaultBroadcastReceiverBinder { public abstract BroadcastReceiver bindPeopleSpaceWidgetProvider( PeopleSpaceWidgetProvider broadcastReceiver); + /** + * + */ + @Binds + @IntoMap + @ClassKey(GuestResumeSessionReceiver.class) + public abstract BroadcastReceiver bindGuestResumeSessionReceiver( + GuestResumeSessionReceiver broadcastReceiver); + + /** + * + */ + @Binds + @IntoMap + @ClassKey(GuestResetOrExitSessionReceiver.class) + public abstract BroadcastReceiver bindGuestResetOrExitSessionReceiver( + GuestResetOrExitSessionReceiver broadcastReceiver); } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java index 5d154c3b4f6b..c870b89d9e0a 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java @@ -178,7 +178,8 @@ public abstract class SystemUIDefaultModule { KeyguardBypassController bypassController, GroupMembershipManager groupManager, VisualStabilityProvider visualStabilityProvider, - ConfigurationController configurationController) { + ConfigurationController configurationController, + @Main Handler handler) { return new HeadsUpManagerPhone( context, headsUpManagerLogger, @@ -186,7 +187,8 @@ public abstract class SystemUIDefaultModule { bypassController, groupManager, visualStabilityProvider, - configurationController + configurationController, + handler ); } diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamWeatherComplication.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamWeatherComplication.java index f5c5a434a077..3d1bc59b433a 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamWeatherComplication.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamWeatherComplication.java @@ -18,10 +18,12 @@ package com.android.systemui.dreams.complication; import static com.android.systemui.dreams.complication.dagger.DreamWeatherComplicationComponent.DreamWeatherComplicationModule.DREAM_WEATHER_COMPLICATION_LAYOUT_PARAMS; import static com.android.systemui.dreams.complication.dagger.DreamWeatherComplicationComponent.DreamWeatherComplicationModule.DREAM_WEATHER_COMPLICATION_VIEW; +import static com.android.systemui.dreams.complication.dagger.DreamWeatherComplicationComponent.DreamWeatherComplicationModule.SMARTSPACE_TRAMPOLINE_ACTIVITY_COMPONENT; import android.app.smartspace.SmartspaceAction; import android.app.smartspace.SmartspaceTarget; import android.content.Context; +import android.content.Intent; import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; import android.text.TextUtils; @@ -31,6 +33,7 @@ import com.android.systemui.CoreStartable; import com.android.systemui.R; import com.android.systemui.dreams.DreamOverlayStateController; import com.android.systemui.dreams.complication.dagger.DreamWeatherComplicationComponent; +import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceTargetListener; import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController; import com.android.systemui.util.ViewController; @@ -132,15 +135,21 @@ public class DreamWeatherComplication implements Complication { */ static class DreamWeatherViewController extends ViewController<TextView> { private final LockscreenSmartspaceController mSmartSpaceController; + private final ActivityStarter mActivityStarter; + private final String mSmartspaceTrampolineActivityComponent; private SmartspaceTargetListener mSmartspaceTargetListener; @Inject DreamWeatherViewController( @Named(DREAM_WEATHER_COMPLICATION_VIEW) TextView view, + @Named(SMARTSPACE_TRAMPOLINE_ACTIVITY_COMPONENT) String smartspaceTrampoline, + ActivityStarter activityStarter, LockscreenSmartspaceController smartspaceController ) { super(view); + mActivityStarter = activityStarter; mSmartSpaceController = smartspaceController; + mSmartspaceTrampolineActivityComponent = smartspaceTrampoline; } @Override @@ -172,6 +181,15 @@ public class DreamWeatherComplication implements Complication { R.dimen.smart_action_button_icon_padding)); } + mView.setOnClickListener(v -> { + final Intent intent = headerAction.getIntent(); + if (intent != null && intent.getComponent() != null + && intent.getComponent().getClassName() + .equals(mSmartspaceTrampolineActivityComponent)) { + mActivityStarter.postStartActivityDismissingKeyguard( + intent, 0 /*delay*/); + } + }); } }); mSmartSpaceController.addListener(mSmartspaceTargetListener); diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamWeatherComplicationComponent.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamWeatherComplicationComponent.java index 536f3dcd2850..a1660f2b43f2 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamWeatherComplicationComponent.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamWeatherComplicationComponent.java @@ -19,6 +19,7 @@ package com.android.systemui.dreams.complication.dagger; import static java.lang.annotation.RetentionPolicy.RUNTIME; +import android.content.Context; import android.view.LayoutInflater; import android.view.ViewGroup; import android.widget.TextView; @@ -76,6 +77,7 @@ public interface DreamWeatherComplicationComponent { String DREAM_WEATHER_COMPLICATION_VIEW = "weather_complication_view"; String DREAM_WEATHER_COMPLICATION_LAYOUT_PARAMS = "weather_complication_layout_params"; + String SMARTSPACE_TRAMPOLINE_ACTIVITY_COMPONENT = "smartspace_trampoline_activity"; // Order weight of insert into parent container int INSERT_ORDER_WEIGHT = 1; @@ -106,5 +108,15 @@ public interface DreamWeatherComplicationComponent { ComplicationLayoutParams.DIRECTION_END, INSERT_ORDER_WEIGHT); } + + /** + * Provides the smartspace trampoline activity component. + */ + @Provides + @DreamWeatherComplicationScope + @Named(SMARTSPACE_TRAMPOLINE_ACTIVITY_COMPONENT) + static String provideSmartspaceTrampolineActivityComponent(Context context) { + return context.getString(R.string.config_smartspaceTrampolineActivityComponent); + } } } diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java index 54b9430eb445..56eb9d2ecdd5 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java @@ -151,6 +151,8 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler { private void setPanelExpansion(float expansion) { mCurrentExpansion = expansion; + mCentralSurfaces.ifPresent(centralSurfaces -> centralSurfaces.setBouncerShowingOverDream( + mCurrentExpansion != KeyguardBouncer.EXPANSION_HIDDEN)); mStatusBarKeyguardViewManager.onPanelExpansionChanged(mCurrentExpansion, false, true); } diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.java b/packages/SystemUI/src/com/android/systemui/flags/Flags.java index afa7d5e0a9c4..94418f498d3b 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.java +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.java @@ -158,6 +158,8 @@ public class Flags { // 1000 - dock public static final BooleanFlag SIMULATE_DOCK_THROUGH_CHARGING = new BooleanFlag(1000, true); + public static final BooleanFlag DOCK_SETUP_ENABLED = new BooleanFlag(1001, false); + // 1100 - windowing @Keep diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java index 5aedbdc20b31..bd00ce61a7e3 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java @@ -34,8 +34,8 @@ import com.android.systemui.util.concurrency.DelayableExecutor; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; import java.util.HashMap; -import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -71,7 +71,7 @@ public class KeyguardIndicationRotateTextViewController extends @Nullable private ShowNextIndication mShowNextIndicationRunnable; // List of indication types to show. The next indication to show is always at index 0 - private final List<Integer> mIndicationQueue = new LinkedList<>(); + private final List<Integer> mIndicationQueue = new ArrayList<>(); private @IndicationType int mCurrIndicationType = INDICATION_TYPE_NONE; private CharSequence mCurrMessage; private long mLastIndicationSwitch; diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt b/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt index 7f25642be5ee..5e810f24eada 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt @@ -33,6 +33,7 @@ import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dump.DumpManager +import com.android.systemui.people.widget.PeopleSpaceWidgetProvider.EXTRA_USER_HANDLE import com.android.systemui.tuner.TunerService import com.android.systemui.util.Utils import com.android.systemui.util.time.SystemClock diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java index ddcba3ae65ae..9e4ee61669a1 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java @@ -117,12 +117,8 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { } mCheckBox.setVisibility(View.GONE); mStatusIcon.setVisibility(View.GONE); - mEndTouchArea.setVisibility(View.GONE); mContainerLayout.setOnClickListener(null); - mContainerLayout.setContentDescription(null); - mTitleText.setTextColor(mController.getColorItemContent()); - mSubTitleText.setTextColor(mController.getColorItemContent()); - mTwoLineTitleText.setTextColor(mController.getColorItemContent()); + mTitleText.setTextColor(mController.getColorInactiveItem()); mSeekBar.getProgressDrawable().setColorFilter( new PorterDuffColorFilter(mController.getColorSeekbarProgress(), PorterDuff.Mode.SRC_IN)); @@ -143,7 +139,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { && !mController.hasAdjustVolumeUserRestriction()) { mProgressBar.getIndeterminateDrawable().setColorFilter( new PorterDuffColorFilter( - mController.getColorItemContent(), + mController.getColorInactiveItem(), PorterDuff.Mode.SRC_IN)); setSingleLineLayout(getItemTitle(device), true /* bFocused */, false /* showSeekBar*/, @@ -158,7 +154,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { mTitleIcon.setAlpha(DEVICE_CONNECTED_ALPHA); mStatusIcon.setImageDrawable( mContext.getDrawable(R.drawable.media_output_status_failed)); - mStatusIcon.setColorFilter(mController.getColorItemContent()); + mStatusIcon.setColorFilter(mController.getColorInactiveItem()); setTwoLineLayout(device, false /* bFocused */, false /* showSeekBar */, false /* showProgressBar */, true /* showSubtitle */, true /* showStatus */); @@ -166,44 +162,40 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { mContainerLayout.setOnClickListener(v -> onItemClick(v, device)); } else if (mController.getSelectedMediaDevice().size() > 1 && isDeviceIncluded(mController.getSelectedMediaDevice(), device)) { - mTitleText.setTextColor(mController.getColorItemContent()); + mTitleText.setTextColor(mController.getColorActiveItem()); setSingleLineLayout(getItemTitle(device), true /* bFocused */, true /* showSeekBar */, false /* showProgressBar */, false /* showStatus */); - setUpContentDescriptionForActiveDevice(device); mCheckBox.setOnCheckedChangeListener(null); mCheckBox.setVisibility(View.VISIBLE); mCheckBox.setChecked(true); - mCheckBox.setOnCheckedChangeListener( - (buttonView, isChecked) -> onGroupActionTriggered(false, device)); - setCheckBoxColor(mCheckBox, mController.getColorItemContent()); + mCheckBox.setOnCheckedChangeListener((buttonView, isChecked) -> { + onCheckBoxClicked(false, device); + }); + setCheckBoxColor(mCheckBox, mController.getColorActiveItem()); initSeekbar(device); - mEndTouchArea.setVisibility(View.VISIBLE); - mEndTouchArea.setOnClickListener(null); - mEndTouchArea.setOnClickListener((v) -> mCheckBox.performClick()); } else if (!mController.hasAdjustVolumeUserRestriction() && currentlyConnected) { mStatusIcon.setImageDrawable( mContext.getDrawable(R.drawable.media_output_status_check)); - mStatusIcon.setColorFilter(mController.getColorItemContent()); - mTitleText.setTextColor(mController.getColorItemContent()); + mStatusIcon.setColorFilter(mController.getColorActiveItem()); + mTitleText.setTextColor(mController.getColorActiveItem()); setSingleLineLayout(getItemTitle(device), true /* bFocused */, true /* showSeekBar */, false /* showProgressBar */, true /* showStatus */); initSeekbar(device); - setUpContentDescriptionForActiveDevice(device); mCurrentActivePosition = position; } else if (isDeviceIncluded(mController.getSelectableMediaDevice(), device)) { mCheckBox.setOnCheckedChangeListener(null); mCheckBox.setVisibility(View.VISIBLE); mCheckBox.setChecked(false); - mCheckBox.setOnCheckedChangeListener( - (buttonView, isChecked) -> onGroupActionTriggered(true, device)); - mEndTouchArea.setVisibility(View.VISIBLE); - mContainerLayout.setOnClickListener(v -> onGroupActionTriggered(true, device)); - setCheckBoxColor(mCheckBox, mController.getColorItemContent()); + mCheckBox.setOnCheckedChangeListener((buttonView, isChecked) -> { + onCheckBoxClicked(true, device); + }); + setCheckBoxColor(mCheckBox, mController.getColorInactiveItem()); setSingleLineLayout(getItemTitle(device), false /* bFocused */, false /* showSeekBar */, false /* showProgressBar */, false /* showStatus */); + mContainerLayout.setOnClickListener(v -> onItemClick(v, device)); } else { setSingleLineLayout(getItemTitle(device), false /* bFocused */); mContainerLayout.setOnClickListener(v -> onItemClick(v, device)); @@ -221,7 +213,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { @Override void onBind(int customizedItem, boolean topMargin, boolean bottomMargin) { if (customizedItem == CUSTOMIZED_ITEM_PAIR_NEW) { - mTitleText.setTextColor(mController.getColorItemContent()); + mTitleText.setTextColor(mController.getColorInactiveItem()); mCheckBox.setVisibility(View.GONE); setSingleLineLayout(mContext.getText(R.string.media_output_dialog_pairing_new), false /* bFocused */); @@ -233,7 +225,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { } } - private void onGroupActionTriggered(boolean isChecked, MediaDevice device) { + private void onCheckBoxClicked(boolean isChecked, MediaDevice device) { if (isChecked && isDeviceIncluded(mController.getSelectableMediaDevice(), device)) { mController.addDeviceToPlayMedia(device); } else if (!isChecked && isDeviceIncluded(mController.getDeselectableMediaDevice(), @@ -257,14 +249,5 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { notifyDataSetChanged(); } } - - private void setUpContentDescriptionForActiveDevice(MediaDevice device) { - mContainerLayout.setClickable(false); - mContainerLayout.setContentDescription( - mContext.getString(device.getDeviceType() - == MediaDevice.MediaDeviceType.TYPE_BLUETOOTH_DEVICE - ? R.string.accessibility_bluetooth_name - : R.string.accessibility_cast_name, device.getName())); - } } } diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java index 9dc29bd6e090..958e9ed9e38b 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java @@ -144,7 +144,6 @@ public abstract class MediaOutputBaseAdapter extends final LinearLayout mTwoLineLayout; final ImageView mStatusIcon; final CheckBox mCheckBox; - final LinearLayout mEndTouchArea; private String mDeviceId; MediaDeviceBaseViewHolder(View view) { @@ -160,7 +159,6 @@ public abstract class MediaOutputBaseAdapter extends mSeekBar = view.requireViewById(R.id.volume_seekbar); mStatusIcon = view.requireViewById(R.id.media_output_item_status); mCheckBox = view.requireViewById(R.id.check_box); - mEndTouchArea = view.requireViewById(R.id.end_action_area); } void onBind(MediaDevice device, boolean topMargin, boolean bottomMargin, int position) { @@ -185,16 +183,14 @@ public abstract class MediaOutputBaseAdapter extends void setSingleLineLayout(CharSequence title, boolean bFocused, boolean showSeekBar, boolean showProgressBar, boolean showStatus) { mTwoLineLayout.setVisibility(View.GONE); - boolean isActive = showSeekBar || showProgressBar; final Drawable backgroundDrawable = - isActive + showSeekBar || showProgressBar ? mContext.getDrawable(R.drawable.media_output_item_background_active) .mutate() : mContext.getDrawable( R.drawable.media_output_item_background) .mutate(); backgroundDrawable.setColorFilter(new PorterDuffColorFilter( - isActive ? mController.getColorConnectedItemBackground() - : mController.getColorItemBackground(), + mController.getColorItemBackground(), PorterDuff.Mode.SRC_IN)); mItemLayout.setBackground(backgroundDrawable); mProgressBar.setVisibility(showProgressBar ? View.VISIBLE : View.GONE); @@ -383,7 +379,7 @@ public abstract class MediaOutputBaseAdapter extends .mutate(); drawable.setColorFilter( new PorterDuffColorFilter(Utils.getColorStateListDefaultColor(mContext, - R.color.media_dialog_item_main_content), + R.color.media_dialog_active_item_main_content), PorterDuff.Mode.SRC_IN)); return drawable; } diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java index e5e7eb66630b..509bc38c6ecf 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java @@ -307,9 +307,10 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements ColorFilter buttonColorFilter = new PorterDuffColorFilter( mAdapter.getController().getColorButtonBackground(), PorterDuff.Mode.SRC_IN); + ColorFilter onlineButtonColorFilter = new PorterDuffColorFilter( + mAdapter.getController().getColorInactiveItem(), PorterDuff.Mode.SRC_IN); mDoneButton.getBackground().setColorFilter(buttonColorFilter); - mStopButton.getBackground().setColorFilter(buttonColorFilter); - mDoneButton.setTextColor(mAdapter.getController().getColorPositiveButtonText()); + mStopButton.getBackground().setColorFilter(onlineButtonColorFilter); } mHeaderIcon.setVisibility(View.VISIBLE); mHeaderIcon.setImageIcon(icon); diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java index 0fbec3baffa6..ced057093c53 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java @@ -121,12 +121,11 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, private MediaOutputMetricLogger mMetricLogger; - private int mColorItemContent; + private int mColorActiveItem; + private int mColorInactiveItem; private int mColorSeekbarProgress; private int mColorButtonBackground; private int mColorItemBackground; - private int mColorConnectedItemBackground; - private int mColorPositiveButtonText; public enum BroadcastNotifyDialog { ACTION_FIRST_LAUNCH, @@ -151,18 +150,16 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, mMetricLogger = new MediaOutputMetricLogger(mContext, mPackageName); mDialogLaunchAnimator = dialogLaunchAnimator; mNearbyMediaDevicesManager = nearbyMediaDevicesManagerOptional.orElse(null); - mColorItemContent = Utils.getColorStateListDefaultColor(mContext, - R.color.media_dialog_item_main_content); + mColorActiveItem = Utils.getColorStateListDefaultColor(mContext, + R.color.media_dialog_active_item_main_content); + mColorInactiveItem = Utils.getColorStateListDefaultColor(mContext, + R.color.media_dialog_inactive_item_main_content); mColorSeekbarProgress = Utils.getColorStateListDefaultColor(mContext, - R.color.media_dialog_seekbar_progress); + android.R.color.system_accent1_200); mColorButtonBackground = Utils.getColorStateListDefaultColor(mContext, - R.color.media_dialog_button_background); - mColorItemBackground = Utils.getColorStateListDefaultColor(mContext, R.color.media_dialog_item_background); - mColorConnectedItemBackground = Utils.getColorStateListDefaultColor(mContext, - R.color.media_dialog_connected_item_background); - mColorPositiveButtonText = Utils.getColorStateListDefaultColor(mContext, - R.color.media_dialog_solid_button_text); + mColorItemBackground = Utils.getColorStateListDefaultColor(mContext, + android.R.color.system_accent2_50); } void start(@NonNull Callback cb) { @@ -342,7 +339,8 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, } void setColorFilter(Drawable drawable, boolean isActive) { - drawable.setColorFilter(new PorterDuffColorFilter(mColorItemContent, + drawable.setColorFilter(new PorterDuffColorFilter(isActive + ? mColorActiveItem : mColorInactiveItem, PorterDuff.Mode.SRC_IN)); } @@ -377,32 +375,26 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, ColorScheme mCurrentColorScheme = new ColorScheme(wallpaperColors, isDarkTheme); if (isDarkTheme) { - mColorItemContent = mCurrentColorScheme.getAccent1().get(2); // A1-100 - mColorSeekbarProgress = mCurrentColorScheme.getAccent2().get(7); // A2-600 - mColorButtonBackground = mCurrentColorScheme.getAccent1().get(4); // A1-300 - mColorItemBackground = mCurrentColorScheme.getNeutral2().get(9); // N2-800 - mColorConnectedItemBackground = mCurrentColorScheme.getAccent2().get(9); // A2-800 - mColorPositiveButtonText = mCurrentColorScheme.getAccent2().get(9); // A2-800 + mColorActiveItem = mCurrentColorScheme.getNeutral1().get(10); + mColorInactiveItem = mCurrentColorScheme.getNeutral1().get(10); + mColorSeekbarProgress = mCurrentColorScheme.getAccent1().get(2); + mColorButtonBackground = mCurrentColorScheme.getAccent1().get(2); + mColorItemBackground = mCurrentColorScheme.getAccent2().get(0); } else { - mColorItemContent = mCurrentColorScheme.getAccent1().get(9); // A1-800 - mColorSeekbarProgress = mCurrentColorScheme.getAccent1().get(4); // A1-300 - mColorButtonBackground = mCurrentColorScheme.getAccent1().get(7); // A1-600 - mColorItemBackground = mCurrentColorScheme.getAccent2().get(1); // A2-50 - mColorConnectedItemBackground = mCurrentColorScheme.getAccent1().get(2); // A1-100 - mColorPositiveButtonText = mCurrentColorScheme.getNeutral1().get(1); // N1-50 + mColorActiveItem = mCurrentColorScheme.getNeutral1().get(10); + mColorInactiveItem = mCurrentColorScheme.getAccent1().get(7); + mColorSeekbarProgress = mCurrentColorScheme.getAccent1().get(3); + mColorButtonBackground = mCurrentColorScheme.getAccent1().get(3); + mColorItemBackground = mCurrentColorScheme.getAccent2().get(0); } } - public int getColorConnectedItemBackground() { - return mColorConnectedItemBackground; - } - - public int getColorPositiveButtonText() { - return mColorPositiveButtonText; + public int getColorActiveItem() { + return mColorActiveItem; } - public int getColorItemContent() { - return mColorItemContent; + public int getColorInactiveItem() { + return mColorInactiveItem; } public int getColorSeekbarProgress() { diff --git a/packages/SystemUI/src/com/android/systemui/privacy/television/TvOngoingPrivacyChip.java b/packages/SystemUI/src/com/android/systemui/privacy/television/TvOngoingPrivacyChip.java index 5510eb172cd7..09c4cb760c90 100644 --- a/packages/SystemUI/src/com/android/systemui/privacy/television/TvOngoingPrivacyChip.java +++ b/packages/SystemUI/src/com/android/systemui/privacy/television/TvOngoingPrivacyChip.java @@ -57,7 +57,6 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Collections; -import java.util.LinkedList; import java.util.List; import javax.inject.Inject; @@ -126,7 +125,7 @@ public class TvOngoingPrivacyChip extends CoreStartable implements PrivacyItemCo private final Runnable mCollapseRunnable = this::collapseChip; private final Runnable mAccessibilityRunnable = this::makeAccessibilityAnnouncement; - private final List<PrivacyItem> mItemsBeforeLastAnnouncement = new LinkedList<>(); + private final List<PrivacyItem> mItemsBeforeLastAnnouncement = new ArrayList<>(); @State private int mState = STATE_NOT_SHOWN; diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java index 76ec6bd086db..f87cb29a8758 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java @@ -612,7 +612,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca } else if (progress > 0 && view.getVisibility() != View.VISIBLE) { view.setVisibility((View.VISIBLE)); } - float alpha = mQSPanelController.bouncerInTransit() + float alpha = mQSPanelController.isBouncerInTransit() ? BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(progress) : ShadeInterpolation.getContentAlpha(progress); view.setAlpha(alpha); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java index 5670836566ab..851307ac615f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java @@ -254,8 +254,8 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> { * * @return if bouncer is in transit */ - public boolean bouncerInTransit() { - return mStatusBarKeyguardViewManager.bouncerIsInTransit(); + public boolean isBouncerInTransit() { + return mStatusBarKeyguardViewManager.isBouncerInTransit(); } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java index f736231bc22b..da5202bc3645 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java @@ -19,9 +19,7 @@ package com.android.systemui.qs.tiles; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothDevice; -import android.content.Context; import android.content.Intent; -import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.Looper; import android.os.UserManager; @@ -134,9 +132,10 @@ public class BluetoothTile extends QSTileImpl<BooleanState> { state.contentDescription = mContext.getString( R.string.accessibility_quick_settings_bluetooth); state.stateDescription = ""; + if (enabled) { if (connected) { - state.icon = new BluetoothConnectedTileIcon(); + state.icon = ResourceIcon.get(R.drawable.qs_bluetooth_icon_on); if (!TextUtils.isEmpty(mController.getConnectedDeviceName())) { state.label = mController.getConnectedDeviceName(); } @@ -145,21 +144,19 @@ public class BluetoothTile extends QSTileImpl<BooleanState> { + ", " + state.secondaryLabel; } else if (state.isTransient) { state.icon = ResourceIcon.get( - com.android.internal.R.drawable.ic_bluetooth_transient_animation); + R.drawable.qs_bluetooth_icon_search); state.stateDescription = state.secondaryLabel; } else { state.icon = - ResourceIcon.get(com.android.internal.R.drawable.ic_qs_bluetooth); + ResourceIcon.get(R.drawable.qs_bluetooth_icon_off); state.stateDescription = mContext.getString(R.string.accessibility_not_connected); } state.state = Tile.STATE_ACTIVE; } else { - state.icon = ResourceIcon.get(com.android.internal.R.drawable.ic_qs_bluetooth); + state.icon = ResourceIcon.get(R.drawable.qs_bluetooth_icon_off); state.state = Tile.STATE_INACTIVE; } - state.dualLabelContentDescription = mContext.getResources().getString( - R.string.accessibility_quick_settings_open_settings, getTileLabel()); state.expandedAccessibilityClassName = Switch.class.getName(); } @@ -244,22 +241,4 @@ public class BluetoothTile extends QSTileImpl<BooleanState> { refreshState(); } }; - - /** - * Bluetooth icon wrapper (when connected with no battery indicator) for Quick Settings. This is - * used instead of {@link com.android.systemui.qs.tileimpl.QSTileImpl.DrawableIcon} in order to - * use a context that reflects dark/light theme attributes. - */ - private class BluetoothConnectedTileIcon extends Icon { - - BluetoothConnectedTileIcon() { - // Do nothing. Default constructor to limit visibility. - } - - @Override - public Drawable getDrawable(Context context) { - // This method returns Pair<Drawable, String> - the first value is the drawable. - return context.getDrawable(R.drawable.ic_bluetooth_connected); - } - } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java index 177c82ed3d78..600874f0d01a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java @@ -57,6 +57,7 @@ import javax.inject.Inject; /** Quick settings tile: Rotation **/ public class RotationLockTile extends QSTileImpl<BooleanState> implements BatteryController.BatteryStateChangeCallback { + private static final String EMPTY_SECONDARY_STRING = ""; private final Icon mIcon = ResourceIcon.get(com.android.internal.R.drawable.ic_qs_auto_rotate); private final RotationLockController mController; @@ -144,13 +145,15 @@ public class RotationLockTile extends QSTileImpl<BooleanState> implements && mController.isCameraRotationEnabled(); state.value = !rotationLocked; state.label = mContext.getString(R.string.quick_settings_rotation_unlocked_label); - state.icon = mIcon; + state.icon = ResourceIcon.get(R.drawable.qs_auto_rotate_icon_off); state.contentDescription = getAccessibilityString(rotationLocked); - if (!rotationLocked && cameraRotation) { - state.secondaryLabel = mContext.getResources().getString( - R.string.rotation_lock_camera_rotation_on); + if (!rotationLocked) { + state.secondaryLabel = cameraRotation ? mContext.getResources().getString( + R.string.rotation_lock_camera_rotation_on) + : EMPTY_SECONDARY_STRING; + state.icon = ResourceIcon.get(R.drawable.qs_auto_rotate_icon_on); } else { - state.secondaryLabel = ""; + state.secondaryLabel = EMPTY_SECONDARY_STRING; } state.stateDescription = state.secondaryLabel; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java index 8ca095d9a609..c481b2c6090f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java @@ -342,12 +342,7 @@ public class InternetDialog extends SystemUIDialog implements private void setOnClickListener() { mMobileNetworkLayout.setOnClickListener(v -> { - if (mInternetDialogController.isMobileDataEnabled() - && !mInternetDialogController.isDeviceLocked()) { - if (!mInternetDialogController.activeNetworkIsCellular()) { - mInternetDialogController.connectCarrierNetwork(); - } - } + mInternetDialogController.connectCarrierNetwork(); }); mMobileDataToggle.setOnCheckedChangeListener( (buttonView, isChecked) -> { 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 d97ce7757d8c..607cfa116749 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 @@ -649,12 +649,40 @@ public class InternetDialogController implements AccessPointController.AccessPoi } void connectCarrierNetwork() { - final MergedCarrierEntry mergedCarrierEntry = + String errorLogPrefix = "Fail to connect carrier network : "; + + if (!isMobileDataEnabled()) { + if (DEBUG) { + Log.d(TAG, errorLogPrefix + "settings OFF"); + } + return; + } + if (isDeviceLocked()) { + if (DEBUG) { + Log.d(TAG, errorLogPrefix + "device locked"); + } + return; + } + if (activeNetworkIsCellular()) { + Log.d(TAG, errorLogPrefix + "already active"); + return; + } + + MergedCarrierEntry mergedCarrierEntry = mAccessPointController.getMergedCarrierEntry(); - if (mergedCarrierEntry != null && mergedCarrierEntry.canConnect()) { - mergedCarrierEntry.connect(null /* ConnectCallback */, false); - makeOverlayToast(R.string.wifi_wont_autoconnect_for_now); + if (mergedCarrierEntry == null) { + Log.e(TAG, errorLogPrefix + "no merged entry"); + return; } + + if (!mergedCarrierEntry.canConnect()) { + Log.w(TAG, errorLogPrefix + "merged entry connect state " + + mergedCarrierEntry.getConnectedState()); + return; + } + + mergedCarrierEntry.connect(null /* ConnectCallback */, false); + makeOverlayToast(R.string.wifi_wont_autoconnect_for_now); } boolean isCarrierNetworkActive() { diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt index 3a6248b793d0..6b79a282c75f 100644 --- a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt @@ -30,9 +30,9 @@ import androidx.annotation.GuardedBy import androidx.annotation.WorkerThread import com.android.systemui.Dumpable import com.android.systemui.dump.DumpManager +import com.android.systemui.people.widget.PeopleSpaceWidgetProvider.EXTRA_USER_HANDLE import com.android.systemui.util.Assert import java.io.PrintWriter -import java.lang.IllegalStateException import java.lang.ref.WeakReference import java.util.concurrent.Executor import kotlin.properties.ReadWriteProperty diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java index 6cfbb43fa25a..1ffa6f41d8a3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java @@ -19,13 +19,12 @@ package com.android.systemui.statusbar; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Handler; -import android.os.Looper; import android.os.SystemClock; import android.util.ArrayMap; import android.util.ArraySet; import android.view.accessibility.AccessibilityEvent; -import com.android.internal.annotations.VisibleForTesting; +import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag; import com.android.systemui.statusbar.policy.HeadsUpManagerLogger; @@ -43,8 +42,9 @@ public abstract class AlertingNotificationManager implements NotificationLifetim protected final ArrayMap<String, AlertEntry> mAlertEntries = new ArrayMap<>(); protected final HeadsUpManagerLogger mLogger; - public AlertingNotificationManager(HeadsUpManagerLogger logger) { + public AlertingNotificationManager(HeadsUpManagerLogger logger, @Main Handler handler) { mLogger = logger; + mHandler = handler; } /** @@ -57,8 +57,7 @@ public abstract class AlertingNotificationManager implements NotificationLifetim protected NotificationSafeToRemoveCallback mNotificationLifetimeFinishedCallback; protected int mMinimumDisplayTime; protected int mAutoDismissNotificationDecay; - @VisibleForTesting - public Handler mHandler = new Handler(Looper.getMainLooper()); + private final Handler mHandler; /** * Called when posting a new notification that should alert the user and appear on screen. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkController.java index f960eb7b6e9b..ed32008526d8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkController.java @@ -47,8 +47,6 @@ public interface NetworkController extends CallbackController<SignalCallback>, D void addEmergencyListener(EmergencyListener listener); /** */ void removeEmergencyListener(EmergencyListener listener); - /** */ - boolean hasEmergencyCryptKeeperText(); /** */ boolean isRadioOn(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java index dea429f6c617..46bfb50c8f2f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java @@ -81,7 +81,6 @@ import com.android.systemui.statusbar.policy.DataSaverController; import com.android.systemui.statusbar.policy.DataSaverControllerImpl; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener; -import com.android.systemui.statusbar.policy.EncryptionHelper; import com.android.systemui.telephony.TelephonyListenerManager; import com.android.systemui.util.CarrierConfigTracker; @@ -1446,11 +1445,6 @@ public class NetworkControllerImpl extends BroadcastReceiver } /** */ - public boolean hasEmergencyCryptKeeperText() { - return EncryptionHelper.IS_DATA_ENCRYPTED; - } - - /** */ public boolean isRadioOn() { return !mAirplaneMode; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java index aac5b8d6b2eb..4895fa3fcb56 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java @@ -19,12 +19,12 @@ package com.android.systemui.statusbar.notification.collection.coordinator; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.StatusBarState; -import com.android.systemui.statusbar.notification.SectionHeaderVisibilityProvider; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter; import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider; +import com.android.systemui.statusbar.notification.collection.provider.SectionHeaderVisibilityProvider; import com.android.systemui.statusbar.notification.interruption.KeyguardNotificationVisibilityProvider; import javax.inject.Inject; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java index 57fd1975e13a..5ac481341d43 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java @@ -20,7 +20,6 @@ import android.annotation.NonNull; import android.annotation.Nullable; import com.android.systemui.plugins.statusbar.StatusBarStateController; -import com.android.systemui.statusbar.notification.SectionClassifier; import com.android.systemui.statusbar.notification.collection.ListEntry; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; @@ -28,6 +27,7 @@ import com.android.systemui.statusbar.notification.collection.coordinator.dagger import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner; import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider; +import com.android.systemui.statusbar.notification.collection.provider.SectionStyleProvider; import com.android.systemui.statusbar.notification.collection.render.NodeController; import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController; import com.android.systemui.statusbar.notification.dagger.AlertingHeader; @@ -51,7 +51,7 @@ public class RankingCoordinator implements Coordinator { public static final boolean SHOW_ALL_SECTIONS = false; private final StatusBarStateController mStatusBarStateController; private final HighPriorityProvider mHighPriorityProvider; - private final SectionClassifier mSectionClassifier; + private final SectionStyleProvider mSectionStyleProvider; private final NodeController mSilentNodeController; private final SectionHeaderController mSilentHeaderController; private final NodeController mAlertingHeaderController; @@ -62,13 +62,13 @@ public class RankingCoordinator implements Coordinator { public RankingCoordinator( StatusBarStateController statusBarStateController, HighPriorityProvider highPriorityProvider, - SectionClassifier sectionClassifier, + SectionStyleProvider sectionStyleProvider, @AlertingHeader NodeController alertingHeaderController, @SilentHeader SectionHeaderController silentHeaderController, @SilentHeader NodeController silentNodeController) { mStatusBarStateController = statusBarStateController; mHighPriorityProvider = highPriorityProvider; - mSectionClassifier = sectionClassifier; + mSectionStyleProvider = sectionStyleProvider; mAlertingHeaderController = alertingHeaderController; mSilentNodeController = silentNodeController; mSilentHeaderController = silentHeaderController; @@ -77,7 +77,7 @@ public class RankingCoordinator implements Coordinator { @Override public void attach(NotifPipeline pipeline) { mStatusBarStateController.addCallback(mStatusBarStateCallback); - mSectionClassifier.setMinimizedSections(Collections.singleton(mMinimizedNotifSectioner)); + mSectionStyleProvider.setMinimizedSections(Collections.singleton(mMinimizedNotifSectioner)); pipeline.addPreGroupFilter(mSuspendedFilter); pipeline.addPreGroupFilter(mDndVisualEffectsFilter); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinator.kt index 4e9d3ac07a96..9e8b35af1bce 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinator.kt @@ -19,11 +19,11 @@ package com.android.systemui.statusbar.notification.collection.coordinator import android.content.Context import com.android.systemui.R import com.android.systemui.statusbar.notification.AssistantFeedbackController -import com.android.systemui.statusbar.notification.SectionClassifier import com.android.systemui.statusbar.notification.collection.ListEntry import com.android.systemui.statusbar.notification.collection.NotifPipeline import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope +import com.android.systemui.statusbar.notification.collection.provider.SectionStyleProvider import com.android.systemui.statusbar.notification.collection.render.NotifRowController import javax.inject.Inject @@ -35,7 +35,7 @@ import javax.inject.Inject class RowAppearanceCoordinator @Inject internal constructor( context: Context, private var mAssistantFeedbackController: AssistantFeedbackController, - private var mSectionClassifier: SectionClassifier + private var mSectionStyleProvider: SectionStyleProvider ) : Coordinator { private var entryToExpand: NotificationEntry? = null @@ -55,7 +55,7 @@ class RowAppearanceCoordinator @Inject internal constructor( private fun onBeforeRenderList(list: List<ListEntry>) { entryToExpand = list.firstOrNull()?.representativeEntry?.takeIf { entry -> - !mSectionClassifier.isMinimizedSection(entry.section!!) + !mSectionStyleProvider.isMinimizedSection(entry.section!!) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt index 497691d18844..2227be120309 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt @@ -17,9 +17,9 @@ package com.android.systemui.statusbar.notification.collection.inflation import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.statusbar.notification.SectionClassifier import com.android.systemui.statusbar.notification.collection.GroupEntry import com.android.systemui.statusbar.notification.collection.NotificationEntry +import com.android.systemui.statusbar.notification.collection.provider.SectionStyleProvider import javax.inject.Inject /** @@ -28,13 +28,13 @@ import javax.inject.Inject */ @SysUISingleton open class NotifUiAdjustmentProvider @Inject constructor( - private val sectionClassifier: SectionClassifier + private val sectionStyleProvider: SectionStyleProvider ) { private fun isEntryMinimized(entry: NotificationEntry): Boolean { val section = entry.section ?: error("Entry must have a section to determine if minimized") val parent = entry.parent ?: error("Entry must have a parent to determine if minimized") - val isMinimizedSection = sectionClassifier.isMinimizedSection(section) + val isMinimizedSection = sectionStyleProvider.isMinimizedSection(section) val isTopLevelEntry = parent == GroupEntry.ROOT_ENTRY val isGroupSummary = parent.summary == entry return isMinimizedSection && (isTopLevelEntry || isGroupSummary) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/SectionHeaderVisibilityProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SectionHeaderVisibilityProvider.kt index 68bdd18c9881..2148d3bb336a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/SectionHeaderVisibilityProvider.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SectionHeaderVisibilityProvider.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.statusbar.notification +package com.android.systemui.statusbar.notification.collection.provider import android.content.Context import com.android.systemui.dagger.SysUISingleton @@ -34,7 +34,7 @@ import javax.inject.Inject class SectionHeaderVisibilityProvider @Inject constructor( context: Context ) { - var neverShowSectionHeaders = context.resources.getBoolean(R.bool.config_notification_never_show_section_headers) - private set + val neverShowSectionHeaders = + context.resources.getBoolean(R.bool.config_notification_never_show_section_headers) var sectionHeadersVisible = true } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/SectionClassifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SectionStyleProvider.kt index 1f2d0fe6c46e..50e7d1ce4ba0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/SectionClassifier.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SectionStyleProvider.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.statusbar.notification +package com.android.systemui.statusbar.notification.collection.provider import com.android.systemui.dagger.SysUISingleton import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection @@ -26,7 +26,7 @@ import javax.inject.Inject * NOTE: This class exists to avoid putting metadata like "isMinimized" on the NotifSection */ @SysUISingleton -class SectionClassifier @Inject constructor() { +class SectionStyleProvider @Inject constructor() { private lateinit var lowPrioritySections: Set<NotifSectioner> /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilder.kt index 6db544c77f87..75a71af7a0d4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilder.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilder.kt @@ -16,12 +16,12 @@ package com.android.systemui.statusbar.notification.collection.render -import com.android.systemui.statusbar.notification.SectionHeaderVisibilityProvider import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager import com.android.systemui.statusbar.notification.collection.GroupEntry import com.android.systemui.statusbar.notification.collection.ListEntry import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection +import com.android.systemui.statusbar.notification.collection.provider.SectionHeaderVisibilityProvider import com.android.systemui.util.Compile import com.android.systemui.util.traceSection diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt index 6ed81078c3a4..51dc72848d9e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt @@ -19,10 +19,10 @@ package com.android.systemui.statusbar.notification.collection.render import android.content.Context import android.view.View import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager -import com.android.systemui.statusbar.notification.SectionHeaderVisibilityProvider import com.android.systemui.statusbar.notification.collection.GroupEntry import com.android.systemui.statusbar.notification.collection.ListEntry import com.android.systemui.statusbar.notification.collection.NotificationEntry +import com.android.systemui.statusbar.notification.collection.provider.SectionHeaderVisibilityProvider import com.android.systemui.statusbar.notification.stack.NotificationListContainer import com.android.systemui.util.traceSection import dagger.assisted.Assisted diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java index ec770d8a1497..9acd60eb862a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java @@ -31,6 +31,7 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow import com.android.systemui.statusbar.notification.row.ExpandableView; import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.BypassController; import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.SectionProvider; +import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; import javax.inject.Inject; @@ -45,6 +46,10 @@ public class AmbientState { private final SectionProvider mSectionProvider; private final BypassController mBypassController; + /** + * Used to read bouncer states. + */ + private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; private int mScrollY; private boolean mDimmed; private ActivatableNotificationView mActivatedChild; @@ -221,9 +226,11 @@ public class AmbientState { public AmbientState( Context context, @NonNull SectionProvider sectionProvider, - @NonNull BypassController bypassController) { + @NonNull BypassController bypassController, + @Nullable StatusBarKeyguardViewManager statusBarKeyguardViewManager) { mSectionProvider = sectionProvider; mBypassController = bypassController; + mStatusBarKeyguardViewManager = statusBarKeyguardViewManager; reload(context); } @@ -678,4 +685,14 @@ public class AmbientState { public int getStackTopMargin() { return mStackTopMargin; } + + /** + * Check to see if we are about to show bouncer. + * + * @return if bouncer expansion is between 0 and 1. + */ + public boolean isBouncerInTransit() { + return mStatusBarKeyguardViewManager != null + && mStatusBarKeyguardViewManager.isBouncerInTransit(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java index 17844fff67ce..22242b8fb4b4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java @@ -27,6 +27,7 @@ import android.view.ViewGroup; import androidx.annotation.VisibleForTesting; import com.android.internal.policy.SystemBarUtils; +import com.android.keyguard.BouncerPanelExpansionCalculator; import com.android.systemui.R; import com.android.systemui.animation.ShadeInterpolation; import com.android.systemui.statusbar.EmptyShadeView; @@ -435,7 +436,9 @@ public class StackScrollAlgorithm { } else if (ambientState.isExpansionChanging()) { // Adjust alpha for shade open & close. float expansion = ambientState.getExpansionFraction(); - viewState.alpha = ShadeInterpolation.getContentAlpha(expansion); + viewState.alpha = ambientState.isBouncerInTransit() + ? BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(expansion) + : ShadeInterpolation.getContentAlpha(expansion); } if (ambientState.isShadeExpanded() && view.mustStayOnScreen() diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java index 5e81b5da2455..a1dbf0c3f5b6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java @@ -468,6 +468,7 @@ public class CentralSurfaces extends CoreStartable implements */ protected int mState; // TODO: remove this. Just use StatusBarStateController protected boolean mBouncerShowing; + private boolean mBouncerShowingOverDream; private final PhoneStatusBarPolicy mIconPolicy; @@ -3251,9 +3252,13 @@ public class CentralSurfaces extends CoreStartable implements } public boolean onBackPressed() { - boolean isScrimmedBouncer = mScrimController.getState() == ScrimState.BOUNCER_SCRIMMED; - if (mStatusBarKeyguardViewManager.onBackPressed(isScrimmedBouncer /* hideImmediately */)) { - if (isScrimmedBouncer) { + final boolean isScrimmedBouncer = + mScrimController.getState() == ScrimState.BOUNCER_SCRIMMED; + final boolean isBouncerOverDream = isBouncerShowingOverDream(); + + if (mStatusBarKeyguardViewManager.onBackPressed( + isScrimmedBouncer || isBouncerOverDream /* hideImmediately */)) { + if (isScrimmedBouncer || isBouncerOverDream) { mStatusBarStateController.setLeaveOpenOnKeyguardHide(false); } else { mNotificationPanelViewController.expandWithoutQs(); @@ -3275,7 +3280,8 @@ public class CentralSurfaces extends CoreStartable implements if (mNotificationPanelViewController.closeUserSwitcherIfOpen()) { return true; } - if (mState != StatusBarState.KEYGUARD && mState != StatusBarState.SHADE_LOCKED) { + if (mState != StatusBarState.KEYGUARD && mState != StatusBarState.SHADE_LOCKED + && !isBouncerOverDream) { if (mNotificationPanelViewController.canPanelBeCollapsed()) { mShadeController.animateCollapsePanels(); } @@ -3473,6 +3479,16 @@ public class CentralSurfaces extends CoreStartable implements } /** + * Sets whether the bouncer over dream is showing. Note that the bouncer over dream is handled + * independently of the rest of the notification panel. As a result, setting this state via + * {@link #setBouncerShowing(boolean)} leads to unintended side effects from states modified + * behind the dream. + */ + public void setBouncerShowingOverDream(boolean bouncerShowingOverDream) { + mBouncerShowingOverDream = bouncerShowingOverDream; + } + + /** * Propagate the bouncer state to status bar components. * * Separate from {@link #setBouncerShowing} because we sometimes re-create the status bar and @@ -4145,7 +4161,7 @@ public class CentralSurfaces extends CoreStartable implements } public boolean isBouncerShowingOverDream() { - return isBouncerShowing() && mDreamOverlayStateController.isOverlayActive(); + return mBouncerShowingOverDream; } /** 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 415bd90ed23a..f3ee64ff05ba 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java @@ -21,6 +21,7 @@ import android.annotation.Nullable; import android.content.Context; import android.content.res.Resources; import android.graphics.Region; +import android.os.Handler; import android.util.Pools; import androidx.collection.ArraySet; @@ -29,6 +30,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.policy.SystemBarUtils; import com.android.systemui.Dumpable; import com.android.systemui.R; +import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener; import com.android.systemui.statusbar.StatusBarState; @@ -104,8 +106,9 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable, KeyguardBypassController bypassController, GroupMembershipManager groupMembershipManager, VisualStabilityProvider visualStabilityProvider, - ConfigurationController configurationController) { - super(context, logger); + ConfigurationController configurationController, + @Main Handler handler) { + super(context, logger, handler); Resources resources = mContext.getResources(); mExtensionTime = resources.getInteger(R.integer.ambient_notification_extension_time); statusBarStateController.addCallback(mStatusBarStateListener); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java index d492c57dfa0c..711b7e08a7ba 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java @@ -48,7 +48,6 @@ import android.view.animation.Interpolator; import com.android.internal.jank.InteractionJankMonitor; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.util.LatencyTracker; -import com.android.keyguard.BouncerPanelExpansionCalculator; import com.android.systemui.DejankUtils; import com.android.systemui.R; import com.android.systemui.animation.Interpolators; @@ -424,6 +423,8 @@ public abstract class PanelViewController { // situations, such keeping your finger down while swiping to unlock to an app // that is locked in landscape (the rotation will cancel the touch event). expand = false; + } else if (mCentralSurfaces.isBouncerShowingOverDream()) { + expand = false; } else { // If we get a cancel, put the shade back to the state it was in when the // gesture started @@ -796,9 +797,7 @@ public abstract class PanelViewController { } mExpandedFraction = Math.min(1f, maxPanelHeight == 0 ? 0 : mExpandedHeight / maxPanelHeight); - mAmbientState.setExpansionFraction(mStatusBarKeyguardViewManager.bouncerIsInTransit() - ? BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(mExpandedFraction) - : mExpandedFraction); + mAmbientState.setExpansionFraction(mExpandedFraction); onHeightUpdated(mExpandedHeight); updatePanelExpansionAndVisibility(); }); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index b25dbe8869a9..35aee6645289 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -1078,7 +1078,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump } private float getInterpolatedFraction() { - if (mStatusBarKeyguardViewManager.bouncerIsInTransit()) { + if (mStatusBarKeyguardViewManager.isBouncerInTransit()) { return BouncerPanelExpansionCalculator .aboutToShowBouncerProgress(mPanelExpansionFraction); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt index 67de4e3b3c39..6b700a7f4519 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt @@ -38,7 +38,6 @@ import com.android.systemui.util.leak.RotationUtils.ROTATION_UPSIDE_DOWN import com.android.systemui.util.leak.RotationUtils.Rotation import com.android.systemui.util.leak.RotationUtils.getExactRotation import com.android.systemui.util.leak.RotationUtils.getResourcesForRotation - import java.io.PrintWriter import java.lang.Math.max import javax.inject.Inject 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 6ea635a582d1..dd166dd3610e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -1390,7 +1390,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb /** * Returns if bouncer expansion is between 0 and 1 non-inclusive. */ - public boolean bouncerIsInTransit() { + public boolean isBouncerInTransit() { if (mBouncer == null) return false; return mBouncer.inTransit(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java index 06532c4f9d17..61051c2856ac 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java @@ -38,7 +38,6 @@ import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.NotificationShelf; import com.android.systemui.statusbar.NotificationShelfController; import com.android.systemui.statusbar.OperatorNameViewController; -import com.android.systemui.statusbar.connectivity.NetworkController; import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler; import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfComponent; import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout; @@ -261,7 +260,6 @@ public abstract class StatusBarViewModule { StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager, KeyguardStateController keyguardStateController, NotificationPanelViewController notificationPanelViewController, - NetworkController networkController, StatusBarStateController statusBarStateController, CommandQueue commandQueue, CarrierConfigTracker carrierConfigTracker, @@ -281,7 +279,6 @@ public abstract class StatusBarViewModule { statusBarHideIconsForBouncerManager, keyguardStateController, notificationPanelViewController, - networkController, statusBarStateController, commandQueue, carrierConfigTracker, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java index 597c949168d4..670ba96ca1ff 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java @@ -53,9 +53,6 @@ import com.android.systemui.statusbar.DisableFlagsLogger.DisableState; import com.android.systemui.statusbar.OperatorNameView; import com.android.systemui.statusbar.OperatorNameViewController; import com.android.systemui.statusbar.StatusBarState; -import com.android.systemui.statusbar.connectivity.IconState; -import com.android.systemui.statusbar.connectivity.NetworkController; -import com.android.systemui.statusbar.connectivity.SignalCallback; import com.android.systemui.statusbar.events.SystemStatusAnimationCallback; import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler; import com.android.systemui.statusbar.phone.NotificationIconAreaController; @@ -69,7 +66,6 @@ import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentCom import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController; import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallListener; import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager; -import com.android.systemui.statusbar.policy.EncryptionHelper; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.CarrierConfigTracker; import com.android.systemui.util.CarrierConfigTracker.CarrierConfigChangedListener; @@ -101,7 +97,6 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue private final StatusBarStateController mStatusBarStateController; private final KeyguardStateController mKeyguardStateController; private final NotificationPanelViewController mNotificationPanelViewController; - private final NetworkController mNetworkController; private LinearLayout mSystemIconArea; private View mClockView; private View mOngoingCallChip; @@ -127,13 +122,6 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue private List<String> mBlockedIcons = new ArrayList<>(); - private SignalCallback mSignalCallback = new SignalCallback() { - @Override - public void setIsAirplaneMode(@NonNull IconState icon) { - mCommandQueue.recomputeDisableFlags(getContext().getDisplayId(), true /* animate */); - } - }; - private final OngoingCallListener mOngoingCallListener = new OngoingCallListener() { @Override public void onOngoingCallStateChanged(boolean animate) { @@ -178,7 +166,6 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager, KeyguardStateController keyguardStateController, NotificationPanelViewController notificationPanelViewController, - NetworkController networkController, StatusBarStateController statusBarStateController, CommandQueue commandQueue, CarrierConfigTracker carrierConfigTracker, @@ -198,7 +185,6 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue mStatusBarHideIconsForBouncerManager = statusBarHideIconsForBouncerManager; mKeyguardStateController = keyguardStateController; mNotificationPanelViewController = notificationPanelViewController; - mNetworkController = networkController; mStatusBarStateController = statusBarStateController; mCommandQueue = commandQueue; mCarrierConfigTracker = carrierConfigTracker; @@ -237,7 +223,6 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue mOngoingCallChip = mStatusBar.findViewById(R.id.ongoing_call_chip); showSystemIconArea(false); showClock(false); - initEmergencyCryptkeeperText(); initOperatorName(); initNotificationIconArea(); mSystemEventAnimator = @@ -316,9 +301,6 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue public void onDestroyView() { super.onDestroyView(); mStatusBarIconController.removeIconGroup(mDarkIconManager); - if (mNetworkController.hasEmergencyCryptKeeperText()) { - mNetworkController.removeCallback(mSignalCallback); - } mCarrierConfigTracker.removeCallback(mCarrierConfigCallback); mCarrierConfigTracker.removeDataSubscriptionChangedListener(mDefaultDataListener); } @@ -414,15 +396,6 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue } - if (mNetworkController != null && EncryptionHelper.IS_DATA_ENCRYPTED) { - if (mNetworkController.hasEmergencyCryptKeeperText()) { - state |= DISABLE_NOTIFICATION_ICONS; - } - if (!mNetworkController.isRadioOn()) { - state |= DISABLE_SYSTEM_INFO; - } - } - // The shelf will be hidden when dozing with a custom clock, we must show notification // icons in this occasion. if (mStatusBarStateController.isDozing() @@ -593,19 +566,6 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue } } - private void initEmergencyCryptkeeperText() { - View emergencyViewStub = mStatusBar.findViewById(R.id.emergency_cryptkeeper_text); - if (mNetworkController.hasEmergencyCryptKeeperText()) { - if (emergencyViewStub != null) { - ((ViewStub) emergencyViewStub).inflate(); - } - mNetworkController.addCallback(mSignalCallback); - } else if (emergencyViewStub != null) { - ViewGroup parent = (ViewGroup) emergencyViewStub.getParent(); - parent.removeView(emergencyViewStub); - } - } - private void initOperatorName() { int subId = SubscriptionManager.getDefaultDataSubscriptionId(); if (mCarrierConfigTracker.getShowOperatorNameInStatusBarConfig(subId)) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java deleted file mode 100644 index f2ee85886dca..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java +++ /dev/null @@ -1,147 +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.policy; - -import android.annotation.Nullable; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.provider.Settings; -import android.telephony.SubscriptionInfo; -import android.telephony.TelephonyManager; -import android.text.TextUtils; -import android.util.AttributeSet; -import android.widget.TextView; - -import com.android.keyguard.KeyguardUpdateMonitor; -import com.android.keyguard.KeyguardUpdateMonitorCallback; -import com.android.systemui.Dependency; - -import java.util.List; - -public class EmergencyCryptkeeperText extends TextView { - - private KeyguardUpdateMonitor mKeyguardUpdateMonitor; - private final KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() { - @Override - public void onPhoneStateChanged(int phoneState) { - update(); - } - - @Override - public void onRefreshCarrierInfo() { - update(); - } - }; - private final BroadcastReceiver mReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(intent.getAction())) { - update(); - } - } - }; - - public EmergencyCryptkeeperText(Context context, @Nullable AttributeSet attrs) { - super(context, attrs); - setVisibility(GONE); - } - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - mKeyguardUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class); - mKeyguardUpdateMonitor.registerCallback(mCallback); - getContext().registerReceiver(mReceiver, - new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED)); - update(); - } - - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - if (mKeyguardUpdateMonitor != null) { - mKeyguardUpdateMonitor.removeCallback(mCallback); - } - getContext().unregisterReceiver(mReceiver); - } - - private boolean iccCardExist(int simState) { - return ((simState == TelephonyManager.SIM_STATE_PIN_REQUIRED) - || (simState == TelephonyManager.SIM_STATE_PUK_REQUIRED) - || (simState == TelephonyManager.SIM_STATE_NETWORK_LOCKED) - || (simState == TelephonyManager.SIM_STATE_READY) - || (simState == TelephonyManager.SIM_STATE_NOT_READY) - || (simState == TelephonyManager.SIM_STATE_PERM_DISABLED) - || (simState == TelephonyManager.SIM_STATE_CARD_IO_ERROR) - || (simState == TelephonyManager.SIM_STATE_CARD_RESTRICTED) - || (simState == TelephonyManager.SIM_STATE_LOADED)); - } - - public void update() { - boolean hasMobile = mContext.getSystemService(TelephonyManager.class).isDataCapable(); - boolean airplaneMode = (Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.AIRPLANE_MODE_ON, 0) == 1); - - if (!hasMobile || airplaneMode) { - setText(null); - setVisibility(GONE); - return; - } - - boolean allSimsMissing = true; - CharSequence displayText = null; - - List<SubscriptionInfo> subs = mKeyguardUpdateMonitor.getFilteredSubscriptionInfo(false); - final int N = subs.size(); - for (int i = 0; i < N; i++) { - int subId = subs.get(i).getSubscriptionId(); - int simState = mKeyguardUpdateMonitor.getSimState(subId); - CharSequence carrierName = subs.get(i).getCarrierName(); - if (iccCardExist(simState) && !TextUtils.isEmpty(carrierName)) { - allSimsMissing = false; - displayText = carrierName; - } - } - if (allSimsMissing) { - if (N != 0) { - // Shows "Emergency calls only" on devices that are voice-capable. - // This depends on mPlmn containing the text "Emergency calls only" when the radio - // has some connectivity. Otherwise it should show "No service" - // Grab the first subscription, because they all should contain the emergency text, - // described above. - displayText = subs.get(0).getCarrierName(); - } else { - // We don't have a SubscriptionInfo to get the emergency calls only from. - // Grab it from the old sticky broadcast if possible instead. We can use it - // here because no subscriptions are active, so we don't have - // to worry about MSIM clashing. - displayText = getContext().getText( - com.android.internal.R.string.emergency_calls_only); - Intent i = getContext().registerReceiver(null, - new IntentFilter(TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED)); - if (i != null) { - displayText = i.getStringExtra(TelephonyManager.EXTRA_PLMN); - } - } - } - - setText(displayText); - setVisibility(TextUtils.isEmpty(displayText) ? GONE : VISIBLE); - } -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EncryptionHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EncryptionHelper.java deleted file mode 100644 index 9c099f91bc8d..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EncryptionHelper.java +++ /dev/null @@ -1,32 +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.policy; - -import android.sysprop.VoldProperties; - -/** - * Helper for determining whether the phone is decrypted yet. - */ -public class EncryptionHelper { - - public static final boolean IS_DATA_ENCRYPTED = isDataEncrypted(); - - private static boolean isDataEncrypted() { - String voldState = VoldProperties.decrypt().orElse(""); - return "1".equals(voldState) || "trigger_restart_min_framework".equals(voldState); - } -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java index bce5a159f79c..e5d5ed48cc9f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java @@ -24,6 +24,7 @@ import android.app.Notification; import android.content.Context; import android.content.res.Resources; import android.database.ContentObserver; +import android.os.Handler; import android.provider.Settings; import android.util.ArrayMap; import android.view.accessibility.AccessibilityManager; @@ -34,6 +35,7 @@ import com.android.internal.logging.UiEventLogger; import com.android.systemui.Dependency; import com.android.systemui.EventLogTags; import com.android.systemui.R; +import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.statusbar.AlertingNotificationManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag; @@ -79,8 +81,9 @@ public abstract class HeadsUpManager extends AlertingNotificationManager { } } - public HeadsUpManager(@NonNull final Context context, HeadsUpManagerLogger logger) { - super(logger); + public HeadsUpManager(@NonNull final Context context, HeadsUpManagerLogger logger, + @Main Handler handler) { + super(logger, handler); mContext = context; mAccessibilityMgr = Dependency.get(AccessibilityManagerWrapper.class); mUiEventLogger = Dependency.get(UiEventLogger.class); @@ -94,7 +97,7 @@ public abstract class HeadsUpManager extends AlertingNotificationManager { mSnoozeLengthMs = Settings.Global.getInt(context.getContentResolver(), SETTING_HEADS_UP_SNOOZE_LENGTH_MS, defaultSnoozeLengthMs); - ContentObserver settingsObserver = new ContentObserver(mHandler) { + ContentObserver settingsObserver = new ContentObserver(handler) { @Override public void onChange(boolean selfChange) { final int packageSnoozeLengthMs = Settings.Global.getInt( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java index 006edcaf41de..ea423ce7020b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java @@ -264,8 +264,12 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene super.onEnd(animation); if (animation.getTypeMask() == WindowInsets.Type.ime()) { mEntry.mRemoteEditImeAnimatingAway = false; - mEntry.mRemoteEditImeVisible = - mEditText.getRootWindowInsets().isVisible(WindowInsets.Type.ime()); + WindowInsets editTextRootWindowInsets = mEditText.getRootWindowInsets(); + if (editTextRootWindowInsets == null) { + Log.w(TAG, "onEnd called on detached view", new Exception()); + } + mEntry.mRemoteEditImeVisible = editTextRootWindowInsets != null + && editTextRootWindowInsets.isVisible(WindowInsets.Type.ime()); if (!mEntry.mRemoteEditImeVisible && !mEditText.mShowImeOnInputConnection) { mController.removeRemoteInput(mEntry, mToken); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java index a3f01c21d137..5eff8cdb635a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java @@ -45,6 +45,7 @@ import android.os.UserManager; import android.provider.Settings; import android.telephony.TelephonyCallback; import android.text.TextUtils; +import android.util.FeatureFlagUtils; import android.util.Log; import android.util.SparseArray; import android.util.SparseBooleanArray; @@ -63,6 +64,7 @@ import com.android.settingslib.RestrictedLockUtilsInternal; import com.android.settingslib.users.UserCreatingDialog; import com.android.settingslib.utils.ThreadUtils; import com.android.systemui.Dumpable; +import com.android.systemui.GuestResetOrExitSessionReceiver; import com.android.systemui.GuestResumeSessionReceiver; import com.android.systemui.R; import com.android.systemui.SystemUISecondaryUserService; @@ -120,6 +122,8 @@ public class UserSwitcherController implements Dumpable { private final ArrayList<WeakReference<BaseUserAdapter>> mAdapters = new ArrayList<>(); @VisibleForTesting final GuestResumeSessionReceiver mGuestResumeSessionReceiver; + @VisibleForTesting + final GuestResetOrExitSessionReceiver mGuestResetOrExitSessionReceiver; private final KeyguardStateController mKeyguardStateController; private final DeviceProvisionedController mDeviceProvisionedController; private final DevicePolicyManager mDevicePolicyManager; @@ -185,7 +189,9 @@ public class UserSwitcherController implements Dumpable { InteractionJankMonitor interactionJankMonitor, LatencyTracker latencyTracker, DumpManager dumpManager, - DialogLaunchAnimator dialogLaunchAnimator) { + DialogLaunchAnimator dialogLaunchAnimator, + GuestResumeSessionReceiver guestResumeSessionReceiver, + GuestResetOrExitSessionReceiver guestResetOrExitSessionReceiver) { mContext = context; mActivityManager = activityManager; mUserTracker = userTracker; @@ -196,15 +202,14 @@ public class UserSwitcherController implements Dumpable { mFalsingManager = falsingManager; mInteractionJankMonitor = interactionJankMonitor; mLatencyTracker = latencyTracker; + mGuestResumeSessionReceiver = guestResumeSessionReceiver; + mGuestResetOrExitSessionReceiver = guestResetOrExitSessionReceiver; mGlobalSettings = globalSettings; - mGuestResumeSessionReceiver = new GuestResumeSessionReceiver( - this, mUserTracker, mUiEventLogger, secureSettings); mBgExecutor = bgExecutor; mLongRunningExecutor = longRunningExecutor; mUiExecutor = uiExecutor; - if (!UserManager.isGuestUserEphemeral()) { - mGuestResumeSessionReceiver.register(mBroadcastDispatcher); - } + mGuestResumeSessionReceiver.register(); + mGuestResetOrExitSessionReceiver.register(); mGuestUserAutoCreated = mContext.getResources().getBoolean( com.android.internal.R.bool.config_guestUserAutoCreated); mGuestIsResetting = new AtomicBoolean(); @@ -274,6 +279,10 @@ public class UserSwitcherController implements Dumpable { refreshUsers(UserHandle.USER_NULL); } + private static boolean isEnableGuestModeUxChanges(Context context) { + return FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.SETTINGS_GUEST_MODE_UX_CHANGES); + } + /** * Refreshes users from UserManager. * @@ -520,20 +529,31 @@ public class UserSwitcherController implements Dumpable { private void onUserListItemClicked(int id, UserRecord record, DialogShower dialogShower) { int currUserId = mUserTracker.getUserId(); + // If switching from guest and guest is ephemeral, then follow the flow + // of showExitGuestDialog to remove current guest, + // and switch to selected user + UserInfo currUserInfo = mUserTracker.getUserInfo(); if (currUserId == id) { if (record.isGuest) { - showExitGuestDialog(id, dialogShower); + showExitGuestDialog(id, currUserInfo.isEphemeral(), dialogShower); } return; } - if (UserManager.isGuestUserEphemeral()) { - // If switching from guest, we want to bring up the guest exit dialog instead of switching - UserInfo currUserInfo = mUserManager.getUserInfo(currUserId); - if (currUserInfo != null && currUserInfo.isGuest()) { - showExitGuestDialog(currUserId, record.resolveId(), dialogShower); + + if (currUserInfo != null && currUserInfo.isGuest()) { + if (isEnableGuestModeUxChanges(mContext)) { + showExitGuestDialog(currUserId, currUserInfo.isEphemeral(), + record.resolveId(), dialogShower); return; + } else { + if (currUserInfo.isEphemeral()) { + showExitGuestDialog(currUserId, currUserInfo.isEphemeral(), + record.resolveId(), dialogShower); + return; + } } } + if (dialogShower != null) { // If we haven't morphed into another dialog, it means we have just switched users. // Then, dismiss the dialog. @@ -555,7 +575,7 @@ public class UserSwitcherController implements Dumpable { } } - private void showExitGuestDialog(int id, DialogShower dialogShower) { + private void showExitGuestDialog(int id, boolean isGuestEphemeral, DialogShower dialogShower) { int newId = UserHandle.USER_SYSTEM; if (mResumeUserOnGuestLogout && mLastNonGuestUser != UserHandle.USER_SYSTEM) { UserInfo info = mUserManager.getUserInfo(mLastNonGuestUser); @@ -563,14 +583,15 @@ public class UserSwitcherController implements Dumpable { newId = info.id; } } - showExitGuestDialog(id, newId, dialogShower); + showExitGuestDialog(id, isGuestEphemeral, newId, dialogShower); } - private void showExitGuestDialog(int id, int targetId, DialogShower dialogShower) { + private void showExitGuestDialog(int id, boolean isGuestEphemeral, + int targetId, DialogShower dialogShower) { if (mExitGuestDialog != null && mExitGuestDialog.isShowing()) { mExitGuestDialog.cancel(); } - mExitGuestDialog = new ExitGuestDialog(mContext, id, targetId); + mExitGuestDialog = new ExitGuestDialog(mContext, id, isGuestEphemeral, targetId); if (dialogShower != null) { dialogShower.showDialog(mExitGuestDialog); } else { @@ -803,6 +824,52 @@ public class UserSwitcherController implements Dumpable { } } + /** + * Exits guest user and switches to previous non-guest user. The guest must be the current + * user. + * + * @param guestUserId user id of the guest user to exit + * @param targetUserId user id of the guest user to exit, set to UserHandle.USER_NULL when + * target user id is not known + * @param forceRemoveGuestOnExit true: remove guest before switching user, + * false: remove guest only if its ephemeral, else keep guest + */ + public void exitGuestUser(@UserIdInt int guestUserId, @UserIdInt int targetUserId, + boolean forceRemoveGuestOnExit) { + UserInfo currentUser = mUserTracker.getUserInfo(); + if (currentUser.id != guestUserId) { + Log.w(TAG, "User requesting to start a new session (" + guestUserId + ")" + + " is not current user (" + currentUser.id + ")"); + return; + } + if (!currentUser.isGuest()) { + Log.w(TAG, "User requesting to start a new session (" + guestUserId + ")" + + " is not a guest"); + return; + } + + int newUserId = UserHandle.USER_SYSTEM; + if (targetUserId == UserHandle.USER_NULL) { + // when target user is not specified switch to last non guest user + if (mResumeUserOnGuestLogout && mLastNonGuestUser != UserHandle.USER_SYSTEM) { + UserInfo info = mUserManager.getUserInfo(mLastNonGuestUser); + if (info != null && info.isEnabled() && info.supportsSwitchToByUser()) { + newUserId = info.id; + } + } + } else { + newUserId = targetUserId; + } + + if (currentUser.isEphemeral() || forceRemoveGuestOnExit) { + mUiEventLogger.log(QSUserSwitcherEvent.QS_USER_GUEST_REMOVE); + removeGuestUser(currentUser.id, newUserId); + } else { + mUiEventLogger.log(QSUserSwitcherEvent.QS_USER_SWITCH); + switchToUserId(newUserId); + } + } + private void scheduleGuestCreation() { if (!mGuestCreationScheduled.compareAndSet(false, true)) { return; @@ -970,9 +1037,14 @@ public class UserSwitcherController implements Dumpable { public String getName(Context context, UserRecord item) { if (item.isGuest) { if (item.isCurrent) { - return context.getString(mController.mGuestUserAutoCreated + if (isEnableGuestModeUxChanges(context)) { + return context.getString( + com.android.settingslib.R.string.guest_exit_quick_settings_button); + } else { + return context.getString(mController.mGuestUserAutoCreated ? com.android.settingslib.R.string.guest_reset_guest : com.android.settingslib.R.string.guest_exit_guest); + } } else { if (item.info != null) { return context.getString(com.android.internal.R.string.guest_name); @@ -989,8 +1061,13 @@ public class UserSwitcherController implements Dumpable { ? com.android.settingslib.R.string.guest_resetting : com.android.internal.R.string.guest_name); } else { - return context.getString( - com.android.settingslib.R.string.guest_new_guest); + if (isEnableGuestModeUxChanges(context)) { + // we always show "guest" as string, instead of "add guest" + return context.getString(com.android.internal.R.string.guest_name); + } else { + return context.getString( + com.android.settingslib.R.string.guest_new_guest); + } } } } @@ -1012,7 +1089,11 @@ public class UserSwitcherController implements Dumpable { protected static Drawable getIconDrawable(Context context, UserRecord item) { int iconRes; if (item.isAddUser) { - iconRes = R.drawable.ic_account_circle_filled; + if (isEnableGuestModeUxChanges(context)) { + iconRes = R.drawable.ic_add; + } else { + iconRes = R.drawable.ic_account_circle_filled; + } } else if (item.isGuest) { iconRes = R.drawable.ic_account_circle; } else if (item.isAddSupervisedUser) { @@ -1157,24 +1238,58 @@ public class UserSwitcherController implements Dumpable { private final int mGuestId; private final int mTargetId; + private final boolean mIsGuestEphemeral; - public ExitGuestDialog(Context context, int guestId, int targetId) { + ExitGuestDialog(Context context, int guestId, boolean isGuestEphemeral, + int targetId) { super(context); - setTitle(mGuestUserAutoCreated - ? com.android.settingslib.R.string.guest_reset_guest_dialog_title - : com.android.settingslib.R.string.guest_remove_guest_dialog_title); - setMessage(context.getString(R.string.guest_exit_guest_dialog_message)); - setButton(DialogInterface.BUTTON_NEUTRAL, - context.getString(android.R.string.cancel), this); - setButton(DialogInterface.BUTTON_POSITIVE, - context.getString(mGuestUserAutoCreated + if (isEnableGuestModeUxChanges(context)) { + if (isGuestEphemeral) { + setTitle(context.getString( + com.android.settingslib.R.string.guest_exit_dialog_title)); + setMessage(context.getString( + com.android.settingslib.R.string.guest_exit_dialog_message)); + setButton(DialogInterface.BUTTON_NEUTRAL, + context.getString(android.R.string.cancel), this); + setButton(DialogInterface.BUTTON_POSITIVE, + context.getString( + com.android.settingslib.R.string.guest_exit_dialog_button), this); + } else { + setTitle(context.getString( + com.android.settingslib + .R.string.guest_exit_dialog_title_non_ephemeral)); + setMessage(context.getString( + com.android.settingslib + .R.string.guest_exit_dialog_message_non_ephemeral)); + setButton(DialogInterface.BUTTON_NEUTRAL, + context.getString(android.R.string.cancel), this); + setButton(DialogInterface.BUTTON_NEGATIVE, + context.getString( + com.android.settingslib.R.string.guest_exit_clear_data_button), + this); + setButton(DialogInterface.BUTTON_POSITIVE, + context.getString( + com.android.settingslib.R.string.guest_exit_save_data_button), + this); + } + } else { + setTitle(mGuestUserAutoCreated + ? com.android.settingslib.R.string.guest_reset_guest_dialog_title + : com.android.settingslib.R.string.guest_remove_guest_dialog_title); + setMessage(context.getString(R.string.guest_exit_guest_dialog_message)); + setButton(DialogInterface.BUTTON_NEUTRAL, + context.getString(android.R.string.cancel), this); + setButton(DialogInterface.BUTTON_POSITIVE, + context.getString(mGuestUserAutoCreated ? com.android.settingslib.R.string.guest_reset_guest_confirm_button : com.android.settingslib.R.string.guest_remove_guest_confirm_button), - this); + this); + } SystemUIDialog.setWindowOnTop(this, mKeyguardStateController.isShowing()); setCanceledOnTouchOutside(false); mGuestId = guestId; mTargetId = targetId; + mIsGuestEphemeral = isGuestEphemeral; } @Override @@ -1184,12 +1299,40 @@ public class UserSwitcherController implements Dumpable { if (mFalsingManager.isFalseTap(penalty)) { return; } - if (which == BUTTON_NEUTRAL) { - cancel(); + if (isEnableGuestModeUxChanges(getContext())) { + if (mIsGuestEphemeral) { + if (which == DialogInterface.BUTTON_POSITIVE) { + mDialogLaunchAnimator.dismissStack(this); + // Ephemeral guest: exit guest, guest is removed by the system + // on exit, since its marked ephemeral + exitGuestUser(mGuestId, mTargetId, false); + } else if (which == DialogInterface.BUTTON_NEGATIVE) { + // Cancel clicked, do nothing + cancel(); + } + } else { + if (which == DialogInterface.BUTTON_POSITIVE) { + mDialogLaunchAnimator.dismissStack(this); + // Non-ephemeral guest: exit guest, guest is not removed by the system + // on exit, since its marked non-ephemeral + exitGuestUser(mGuestId, mTargetId, false); + } else if (which == DialogInterface.BUTTON_NEGATIVE) { + mDialogLaunchAnimator.dismissStack(this); + // Non-ephemeral guest: remove guest and then exit + exitGuestUser(mGuestId, mTargetId, true); + } else if (which == DialogInterface.BUTTON_NEUTRAL) { + // Cancel clicked, do nothing + cancel(); + } + } } else { - mUiEventLogger.log(QSUserSwitcherEvent.QS_USER_GUEST_REMOVE); - mDialogLaunchAnimator.dismissStack(this); - removeGuestUser(mGuestId, mTargetId); + if (which == BUTTON_NEUTRAL) { + cancel(); + } else { + mUiEventLogger.log(QSUserSwitcherEvent.QS_USER_GUEST_REMOVE); + mDialogLaunchAnimator.dismissStack(this); + removeGuestUser(mGuestId, mTargetId); + } } } } @@ -1198,10 +1341,17 @@ public class UserSwitcherController implements Dumpable { final class AddUserDialog extends SystemUIDialog implements DialogInterface.OnClickListener { - public AddUserDialog(Context context) { + AddUserDialog(Context context) { super(context); + setTitle(com.android.settingslib.R.string.user_add_user_title); - setMessage(com.android.settingslib.R.string.user_add_user_message_short); + String message = context.getString( + com.android.settingslib.R.string.user_add_user_message_short); + UserInfo currentUser = mUserTracker.getUserInfo(); + if (currentUser != null && currentUser.isGuest() && currentUser.isEphemeral()) { + message += context.getString(R.string.user_add_user_message_guest_remove); + } + setMessage(message); setButton(DialogInterface.BUTTON_NEUTRAL, context.getString(android.R.string.cancel), this); setButton(DialogInterface.BUTTON_POSITIVE, diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java index b7f90a479518..c92491e58e00 100644 --- a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java +++ b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java @@ -169,7 +169,8 @@ public abstract class TvSystemUIModule { KeyguardBypassController bypassController, GroupMembershipManager groupManager, VisualStabilityProvider visualStabilityProvider, - ConfigurationController configurationController) { + ConfigurationController configurationController, + @Main Handler handler) { return new HeadsUpManagerPhone( context, headsUpManagerLogger, @@ -177,7 +178,8 @@ public abstract class TvSystemUIModule { bypassController, groupManager, visualStabilityProvider, - configurationController + configurationController, + handler ); } diff --git a/packages/SystemUI/src/com/android/systemui/util/condition/Monitor.java b/packages/SystemUI/src/com/android/systemui/util/condition/Monitor.java index d3c6e9aa0da9..313d56febb75 100644 --- a/packages/SystemUI/src/com/android/systemui/util/condition/Monitor.java +++ b/packages/SystemUI/src/com/android/systemui/util/condition/Monitor.java @@ -18,6 +18,7 @@ package com.android.systemui.util.condition; import android.util.Log; +import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.statusbar.policy.CallbackController; import org.jetbrains.annotations.NotNull; @@ -60,21 +61,13 @@ public class Monitor implements CallbackController<Monitor.Callback> { }; @Inject - public Monitor(Executor executor, Set<Condition> conditions, Set<Callback> callbacks) { + public Monitor(@Main Executor executor, Set<Condition> conditions) { mConditions = new HashSet<>(); mExecutor = executor; if (conditions != null) { mConditions.addAll(conditions); } - - if (callbacks == null) { - return; - } - - for (Callback callback : callbacks) { - addCallbackLocked(callback); - } } private void updateConditionMetState() { diff --git a/packages/SystemUI/src/com/android/systemui/util/condition/dagger/MonitorComponent.java b/packages/SystemUI/src/com/android/systemui/util/condition/dagger/MonitorComponent.java index fc67973fe278..8e739d61b4f2 100644 --- a/packages/SystemUI/src/com/android/systemui/util/condition/dagger/MonitorComponent.java +++ b/packages/SystemUI/src/com/android/systemui/util/condition/dagger/MonitorComponent.java @@ -34,8 +34,7 @@ public interface MonitorComponent { */ @Subcomponent.Factory interface Factory { - MonitorComponent create(@BindsInstance Set<Condition> conditions, - @BindsInstance Set<Monitor.Callback> callbacks); + MonitorComponent create(@BindsInstance Set<Condition> conditions); } /** diff --git a/packages/SystemUI/tests/src/com/android/keyguard/TextInterpolatorTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/TextInterpolatorTest.kt index e42d537596c5..603cf3bcef74 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/TextInterpolatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/TextInterpolatorTest.kt @@ -18,6 +18,7 @@ package com.android.keyguard import android.graphics.Bitmap import android.graphics.Canvas +import android.graphics.Color import android.graphics.Typeface import android.graphics.fonts.Font import android.graphics.fonts.FontFamily @@ -194,6 +195,128 @@ class TextInterpolatorTest : SysuiTestCase() { assertThat(expected.sameAs(actual)).isTrue() } + + @Test + fun testGlyphCallback_Empty() { + val layout = makeLayout(BIDI_TEXT, PAINT, TextDirectionHeuristics.RTL) + + val interp = TextInterpolator(layout).apply { + glyphFilter = { glyph, progress -> + } + } + interp.basePaint.set(START_PAINT) + interp.onBasePaintModified() + + interp.targetPaint.set(END_PAINT) + interp.onTargetPaintModified() + + // Just after created TextInterpolator, it should have 0 progress. + val actual = interp.toBitmap(BMP_WIDTH, BMP_HEIGHT) + val expected = makeLayout(BIDI_TEXT, START_PAINT, TextDirectionHeuristics.RTL) + .toBitmap(BMP_WIDTH, BMP_HEIGHT) + + assertThat(expected.sameAs(actual)).isTrue() + } + + @Test + fun testGlyphCallback_Xcoordinate() { + val layout = makeLayout(BIDI_TEXT, PAINT, TextDirectionHeuristics.RTL) + + val interp = TextInterpolator(layout).apply { + glyphFilter = { glyph, progress -> + glyph.x += 30f + } + } + interp.basePaint.set(START_PAINT) + interp.onBasePaintModified() + + interp.targetPaint.set(END_PAINT) + interp.onTargetPaintModified() + + // Just after created TextInterpolator, it should have 0 progress. + val actual = interp.toBitmap(BMP_WIDTH, BMP_HEIGHT) + val expected = makeLayout(BIDI_TEXT, START_PAINT, TextDirectionHeuristics.RTL) + .toBitmap(BMP_WIDTH, BMP_HEIGHT) + + // The glyph position was modified by callback, so the bitmap should not be the same. + // We cannot modify the result of StaticLayout, so we cannot expect the exact bitmaps. + assertThat(expected.sameAs(actual)).isFalse() + } + + @Test + fun testGlyphCallback_Ycoordinate() { + val layout = makeLayout(BIDI_TEXT, PAINT, TextDirectionHeuristics.RTL) + + val interp = TextInterpolator(layout).apply { + glyphFilter = { glyph, progress -> + glyph.y += 30f + } + } + interp.basePaint.set(START_PAINT) + interp.onBasePaintModified() + + interp.targetPaint.set(END_PAINT) + interp.onTargetPaintModified() + + // Just after created TextInterpolator, it should have 0 progress. + val actual = interp.toBitmap(BMP_WIDTH, BMP_HEIGHT) + val expected = makeLayout(BIDI_TEXT, START_PAINT, TextDirectionHeuristics.RTL) + .toBitmap(BMP_WIDTH, BMP_HEIGHT) + + // The glyph position was modified by callback, so the bitmap should not be the same. + // We cannot modify the result of StaticLayout, so we cannot expect the exact bitmaps. + assertThat(expected.sameAs(actual)).isFalse() + } + + @Test + fun testGlyphCallback_TextSize() { + val layout = makeLayout(BIDI_TEXT, PAINT, TextDirectionHeuristics.RTL) + + val interp = TextInterpolator(layout).apply { + glyphFilter = { glyph, progress -> + glyph.textSize += 10f + } + } + interp.basePaint.set(START_PAINT) + interp.onBasePaintModified() + + interp.targetPaint.set(END_PAINT) + interp.onTargetPaintModified() + + // Just after created TextInterpolator, it should have 0 progress. + val actual = interp.toBitmap(BMP_WIDTH, BMP_HEIGHT) + val expected = makeLayout(BIDI_TEXT, START_PAINT, TextDirectionHeuristics.RTL) + .toBitmap(BMP_WIDTH, BMP_HEIGHT) + + // The glyph position was modified by callback, so the bitmap should not be the same. + // We cannot modify the result of StaticLayout, so we cannot expect the exact bitmaps. + assertThat(expected.sameAs(actual)).isFalse() + } + + @Test + fun testGlyphCallback_Color() { + val layout = makeLayout(BIDI_TEXT, PAINT, TextDirectionHeuristics.RTL) + + val interp = TextInterpolator(layout).apply { + glyphFilter = { glyph, progress -> + glyph.color = Color.RED + } + } + interp.basePaint.set(START_PAINT) + interp.onBasePaintModified() + + interp.targetPaint.set(END_PAINT) + interp.onTargetPaintModified() + + // Just after created TextInterpolator, it should have 0 progress. + val actual = interp.toBitmap(BMP_WIDTH, BMP_HEIGHT) + val expected = makeLayout(BIDI_TEXT, START_PAINT, TextDirectionHeuristics.RTL) + .toBitmap(BMP_WIDTH, BMP_HEIGHT) + + // The glyph position was modified by callback, so the bitmap should not be the same. + // We cannot modify the result of StaticLayout, so we cannot expect the exact bitmaps. + assertThat(expected.sameAs(actual)).isFalse() + } } private fun Layout.toBitmap(width: Int, height: Int) = diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java index 03b18ae66d4e..eefc412e3ffa 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java @@ -603,15 +603,25 @@ public class AuthControllerTest extends SysuiTestCase { } @Test + public void testClientNotified_whenTaskStackChangesDuringShow() throws Exception { + switchTask("other_package"); + showDialog(new int[] {1} /* sensorIds */, false /* credentialAllowed */); + + mTestableLooper.processAllMessages(); + + assertNull(mAuthController.mCurrentDialog); + assertNull(mAuthController.mReceiver); + verify(mDialog1).dismissWithoutCallback(true /* animate */); + verify(mReceiver).onDialogDismissed( + eq(BiometricPrompt.DISMISSED_REASON_USER_CANCEL), + eq(null) /* credentialAttestation */); + } + + @Test public void testClientNotified_whenTaskStackChangesDuringAuthentication() throws Exception { showDialog(new int[] {1} /* sensorIds */, false /* credentialAllowed */); - List<ActivityManager.RunningTaskInfo> tasks = new ArrayList<>(); - ActivityManager.RunningTaskInfo taskInfo = mock(ActivityManager.RunningTaskInfo.class); - taskInfo.topActivity = mock(ComponentName.class); - when(taskInfo.topActivity.getPackageName()).thenReturn("other_package"); - tasks.add(taskInfo); - when(mActivityTaskManager.getTasks(anyInt())).thenReturn(tasks); + switchTask("other_package"); mAuthController.mTaskStackListener.onTaskStackChanged(); mTestableLooper.processAllMessages(); @@ -729,6 +739,16 @@ public class AuthControllerTest extends SysuiTestCase { BIOMETRIC_MULTI_SENSOR_FINGERPRINT_AND_FACE); } + private void switchTask(String packageName) { + final List<ActivityManager.RunningTaskInfo> tasks = new ArrayList<>(); + final ActivityManager.RunningTaskInfo taskInfo = + mock(ActivityManager.RunningTaskInfo.class); + taskInfo.topActivity = mock(ComponentName.class); + when(taskInfo.topActivity.getPackageName()).thenReturn(packageName); + tasks.add(taskInfo); + when(mActivityTaskManager.getTasks(anyInt())).thenReturn(tasks); + } + private PromptInfo createTestPromptInfo() { PromptInfo promptInfo = new PromptInfo(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java index d0b3d6d2d2c7..ccbe6f767100 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java @@ -422,7 +422,31 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase { verify(mUiEventLogger).log(BouncerSwipeTouchHandler.DreamEvent.DREAM_BOUNCER_FULLY_VISIBLE); } + /** + * Ensures {@link CentralSurfaces} + */ + @Test + public void testInformBouncerShowingOnExpand() { + swipeToPosition(1f, Direction.UP, 0); + verify(mCentralSurfaces).setBouncerShowingOverDream(true); + } + + /** + * Ensures {@link CentralSurfaces} + */ + @Test + public void testInformBouncerHidingOnCollapse() { + // Must swipe up to set initial state. + swipeToPosition(1f, Direction.UP, 0); + Mockito.clearInvocations(mCentralSurfaces); + + swipeToPosition(0f, Direction.DOWN, 0); + verify(mCentralSurfaces).setBouncerShowingOverDream(false); + } + + private void swipeToPosition(float percent, Direction direction, float velocityY) { + Mockito.clearInvocations(mTouchSession); mTouchHandler.onSessionStart(mTouchSession); ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor = ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class); diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java index 4fbdb7c512bd..a518b808688e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java @@ -190,7 +190,7 @@ public class QSFragmentTest extends SysuiBaseFragmentTest { QSFragment fragment = resumeAndGetFragment(); enableSplitShade(); setStatusBarState(StatusBarState.KEYGUARD); - when(mQSPanelController.bouncerInTransit()).thenReturn(false); + when(mQSPanelController.isBouncerInTransit()).thenReturn(false); int transitionPxAmount = 123; float transitionProgress = 0.5f; @@ -206,7 +206,7 @@ public class QSFragmentTest extends SysuiBaseFragmentTest { QSFragment fragment = resumeAndGetFragment(); enableSplitShade(); setStatusBarState(StatusBarState.KEYGUARD); - when(mQSPanelController.bouncerInTransit()).thenReturn(true); + when(mQSPanelController.isBouncerInTransit()).thenReturn(true); int transitionPxAmount = 123; float transitionProgress = 0.5f; diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt index 689de50d5b4a..69d3f8b313c9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt @@ -61,7 +61,7 @@ class QSPanelControllerTest : SysuiTestCase() { whenever(brightnessSliderFactory.create(any(), any())).thenReturn(brightnessSlider) whenever(brightnessControllerFactory.create(any())).thenReturn(brightnessController) whenever(qsPanel.resources).thenReturn(mContext.orCreateTestableResources.resources) - whenever(statusBarKeyguardViewManager.bouncerIsInTransit()).thenReturn(false) + whenever(statusBarKeyguardViewManager.isBouncerInTransit()).thenReturn(false) controller = QSPanelController( qsPanel, @@ -109,10 +109,10 @@ class QSPanelControllerTest : SysuiTestCase() { } @Test - fun testBouncerIsInTransit() { - whenever(statusBarKeyguardViewManager.bouncerIsInTransit()).thenReturn(true) - assertThat(controller.bouncerInTransit()).isEqualTo(true) - whenever(statusBarKeyguardViewManager.bouncerIsInTransit()).thenReturn(false) - assertThat(controller.bouncerInTransit()).isEqualTo(false) + fun testIsBouncerInTransit() { + whenever(statusBarKeyguardViewManager.isBouncerInTransit()).thenReturn(true) + assertThat(controller.isBouncerInTransit()).isEqualTo(true) + whenever(statusBarKeyguardViewManager.isBouncerInTransit()).thenReturn(false) + assertThat(controller.isBouncerInTransit()).isEqualTo(false) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt index cc472481ad8a..d65901777a73 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt @@ -10,6 +10,7 @@ import android.testing.TestableLooper.RunWithLooper import androidx.test.filters.SmallTest import com.android.internal.logging.MetricsLogger import com.android.internal.logging.testing.UiEventLoggerFake +import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.classifier.FalsingManagerFake import com.android.systemui.plugins.ActivityStarter @@ -18,6 +19,7 @@ import com.android.systemui.plugins.qs.QSTile import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.qs.QSTileHost import com.android.systemui.qs.logging.QSLogger +import com.android.systemui.qs.tileimpl.QSTileImpl import com.android.systemui.statusbar.policy.BluetoothController import com.google.common.truth.Truth.assertThat import org.junit.Before @@ -25,6 +27,7 @@ import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito +import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations @RunWith(AndroidTestingRunner::class) @@ -84,6 +87,53 @@ class BluetoothTileTest : SysuiTestCase() { assertThat(tile.restrictionChecked).isEqualTo(UserManager.DISALLOW_BLUETOOTH) } + @Test + fun testIcon_whenDisabled_isOffState() { + val state = QSTile.BooleanState() + disableBluetooth() + + tile.handleUpdateState(state, /* arg= */ null) + + assertThat(state.icon) + .isEqualTo(QSTileImpl.ResourceIcon.get(R.drawable.qs_bluetooth_icon_off)) + } + + @Test + fun testIcon_whenDisconnected_isOffState() { + val state = QSTile.BooleanState() + enableBluetooth() + setBluetoothDisconnected() + + tile.handleUpdateState(state, /* arg= */ null) + + assertThat(state.icon) + .isEqualTo(QSTileImpl.ResourceIcon.get(R.drawable.qs_bluetooth_icon_off)) + } + + @Test + fun testIcon_whenConnected_isOnState() { + val state = QSTile.BooleanState() + enableBluetooth() + setBluetoothConnected() + + tile.handleUpdateState(state, /* arg= */ null) + + assertThat(state.icon) + .isEqualTo(QSTileImpl.ResourceIcon.get(R.drawable.qs_bluetooth_icon_on)) + } + + @Test + fun testIcon_whenConnecting_isSearchState() { + val state = QSTile.BooleanState() + enableBluetooth() + setBluetoothConnecting() + + tile.handleUpdateState(state, /* arg= */ null) + + assertThat(state.icon) + .isEqualTo(QSTileImpl.ResourceIcon.get(R.drawable.qs_bluetooth_icon_search)) + } + private class FakeBluetoothTile( qsTileHost: QSTileHost, backgroundLooper: Looper, @@ -114,4 +164,27 @@ class BluetoothTileTest : SysuiTestCase() { restrictionChecked = userRestriction } } + + fun enableBluetooth() { + `when`(bluetoothController.isBluetoothEnabled).thenReturn(true) + } + + fun disableBluetooth() { + `when`(bluetoothController.isBluetoothEnabled).thenReturn(false) + } + + fun setBluetoothDisconnected() { + `when`(bluetoothController.isBluetoothConnecting).thenReturn(false) + `when`(bluetoothController.isBluetoothConnected).thenReturn(false) + } + + fun setBluetoothConnected() { + `when`(bluetoothController.isBluetoothConnecting).thenReturn(false) + `when`(bluetoothController.isBluetoothConnected).thenReturn(true) + } + + fun setBluetoothConnecting() { + `when`(bluetoothController.isBluetoothConnected).thenReturn(false) + `when`(bluetoothController.isBluetoothConnecting).thenReturn(true) + } }
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java index 55c51b255ac7..e9dfd3ed182b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java @@ -36,9 +36,11 @@ import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.classifier.FalsingManagerFake; import com.android.systemui.plugins.ActivityStarter; +import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSTileHost; import com.android.systemui.qs.logging.QSLogger; +import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.DeviceStateRotationLockSettingController; import com.android.systemui.statusbar.policy.RotationLockController; @@ -194,6 +196,26 @@ public class RotationLockTileTest extends SysuiTestCase { assertEquals("", mLockTile.getState().secondaryLabel.toString()); } + @Test + public void testIcon_whenDisabled_isOffState() { + QSTile.BooleanState state = new QSTile.BooleanState(); + disableAutoRotation(); + + mLockTile.handleUpdateState(state, /* arg= */ null); + + assertEquals(state.icon, QSTileImpl.ResourceIcon.get(R.drawable.qs_auto_rotate_icon_off)); + } + + @Test + public void testIcon_whenEnabled_isOnState() { + QSTile.BooleanState state = new QSTile.BooleanState(); + enableAutoRotation(); + + mLockTile.handleUpdateState(state, /* arg= */ null); + + assertEquals(state.icon, QSTileImpl.ResourceIcon.get(R.drawable.qs_auto_rotate_icon_on)); + } + private void enableAutoRotation() { when(mRotationPolicyWrapper.isRotationLocked()).thenReturn(false); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java index 633a9c3a03d8..8c16d4dce92b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java @@ -25,6 +25,8 @@ import android.content.Intent; import android.graphics.PixelFormat; import android.graphics.drawable.Drawable; import android.net.ConnectivityManager; +import android.net.Network; +import android.net.NetworkCapabilities; import android.net.wifi.WifiManager; import android.os.Handler; import android.telephony.ServiceState; @@ -85,6 +87,12 @@ public class InternetDialogControllerTest extends SysuiTestCase { @Mock private WifiManager mWifiManager; @Mock + private ConnectivityManager mConnectivityManager; + @Mock + private Network mNetwork; + @Mock + private NetworkCapabilities mNetworkCapabilities; + @Mock private TelephonyManager mTelephonyManager; @Mock private SubscriptionManager mSubscriptionManager; @@ -170,7 +178,7 @@ public class InternetDialogControllerTest extends SysuiTestCase { mInternetDialogController = new InternetDialogController(mContext, mock(UiEventLogger.class), mock(ActivityStarter.class), mAccessPointController, mSubscriptionManager, mTelephonyManager, mWifiManager, - mock(ConnectivityManager.class), mHandler, mExecutor, mBroadcastDispatcher, + mConnectivityManager, mHandler, mExecutor, mBroadcastDispatcher, mock(KeyguardUpdateMonitor.class), mGlobalSettings, mKeyguardStateController, mWindowManager, mToastFactory, mWorkerHandler, mCarrierConfigTracker, mLocationController, mDialogLaunchAnimator); @@ -184,6 +192,14 @@ public class InternetDialogControllerTest extends SysuiTestCase { @Test public void connectCarrierNetwork_mergedCarrierEntryCanConnect_connectAndCreateSysUiToast() { + when(mTelephonyManager.isDataEnabled()).thenReturn(true); + when(mKeyguardStateController.isUnlocked()).thenReturn(true); + when(mConnectivityManager.getActiveNetwork()).thenReturn(mNetwork); + when(mConnectivityManager.getNetworkCapabilities(mNetwork)) + .thenReturn(mNetworkCapabilities); + when(mNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) + .thenReturn(false); + when(mMergedCarrierEntry.canConnect()).thenReturn(true); mTestableResources.addOverride(R.string.wifi_wont_autoconnect_for_now, TOAST_MESSAGE_STRING); @@ -196,6 +212,52 @@ public class InternetDialogControllerTest extends SysuiTestCase { } @Test + public void connectCarrierNetwork_mergedCarrierEntryCanConnect_doNothingWhenSettingsOff() { + when(mTelephonyManager.isDataEnabled()).thenReturn(false); + + mTestableResources.addOverride(R.string.wifi_wont_autoconnect_for_now, + TOAST_MESSAGE_STRING); + mInternetDialogController.connectCarrierNetwork(); + + verify(mMergedCarrierEntry, never()).connect(null /* callback */, false /* showToast */); + verify(mToastFactory, never()).createToast(any(), anyString(), anyString(), anyInt(), + anyInt()); + } + + @Test + public void connectCarrierNetwork_mergedCarrierEntryCanConnect_doNothingWhenKeyguardLocked() { + when(mTelephonyManager.isDataEnabled()).thenReturn(true); + when(mKeyguardStateController.isUnlocked()).thenReturn(false); + + mTestableResources.addOverride(R.string.wifi_wont_autoconnect_for_now, + TOAST_MESSAGE_STRING); + mInternetDialogController.connectCarrierNetwork(); + + verify(mMergedCarrierEntry, never()).connect(null /* callback */, false /* showToast */); + verify(mToastFactory, never()).createToast(any(), anyString(), anyString(), anyInt(), + anyInt()); + } + + @Test + public void connectCarrierNetwork_mergedCarrierEntryCanConnect_doNothingWhenMobileIsPrimary() { + when(mTelephonyManager.isDataEnabled()).thenReturn(true); + when(mKeyguardStateController.isUnlocked()).thenReturn(true); + when(mConnectivityManager.getActiveNetwork()).thenReturn(mNetwork); + when(mConnectivityManager.getNetworkCapabilities(mNetwork)) + .thenReturn(mNetworkCapabilities); + when(mNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) + .thenReturn(true); + + mTestableResources.addOverride(R.string.wifi_wont_autoconnect_for_now, + TOAST_MESSAGE_STRING); + mInternetDialogController.connectCarrierNetwork(); + + verify(mMergedCarrierEntry, never()).connect(null /* callback */, false /* showToast */); + verify(mToastFactory, never()).createToast(any(), anyString(), anyString(), anyInt(), + anyInt()); + } + + @Test public void makeOverlayToast_withGravityFlags_addViewWithLayoutParams() { mTestableResources.addOverride(TOAST_MESSAGE_STRING_ID, TOAST_MESSAGE_STRING); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java index 8a388479c0e7..65d0adc99739 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java @@ -83,12 +83,10 @@ public class AlertingNotificationManagerTest extends SysuiTestCase { private final class TestableAlertingNotificationManager extends AlertingNotificationManager { private AlertEntry mLastCreatedEntry; - private TestableAlertingNotificationManager() { - super(mock(HeadsUpManagerLogger.class)); + private TestableAlertingNotificationManager(Handler handler) { + super(mock(HeadsUpManagerLogger.class), handler); mMinimumDisplayTime = TEST_MINIMUM_DISPLAY_TIME; mAutoDismissNotificationDecay = TEST_AUTO_DISMISS_TIME; - mHandler.removeCallbacksAndMessages(null); - mHandler = mTestHandler; } @Override @@ -109,8 +107,8 @@ public class AlertingNotificationManagerTest extends SysuiTestCase { } } - protected AlertingNotificationManager createAlertingNotificationManager() { - return new TestableAlertingNotificationManager(); + protected AlertingNotificationManager createAlertingNotificationManager(Handler handler) { + return new TestableAlertingNotificationManager(handler); } protected StatusBarNotification createNewSbn(int id, Notification.Builder n) { @@ -144,7 +142,7 @@ public class AlertingNotificationManagerTest extends SysuiTestCase { .build(); mEntry.setRow(mRow); - mAlertingNotificationManager = createAlertingNotificationManager(); + mAlertingNotificationManager = createAlertingNotificationManager(mTestHandler); } @After diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java index d394d7dcebbe..bfaad7c858d4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java @@ -789,8 +789,11 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { mExecutor.runAllReady(); reset(mRotateTextViewController); - // GIVEN keyguard is showing + // GIVEN keyguard is showing and not dozing when(mKeyguardStateController.isShowing()).thenReturn(true); + mController.setVisible(true); + mExecutor.runAllReady(); + reset(mRotateTextViewController); // WHEN keyguard showing changed called mKeyguardStateControllerCallback.onKeyguardShowingChanged(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java index 52bacd2360b3..d8a98d1e8ea4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java @@ -29,12 +29,12 @@ import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.SysuiTestCase; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.plugins.statusbar.StatusBarStateController; -import com.android.systemui.statusbar.notification.SectionHeaderVisibilityProvider; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter; import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider; +import com.android.systemui.statusbar.notification.collection.provider.SectionHeaderVisibilityProvider; import com.android.systemui.statusbar.notification.interruption.KeyguardNotificationVisibilityProvider; import com.android.systemui.statusbar.policy.KeyguardStateController; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java index 3b034f7af9a6..fc74f3954dc9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java @@ -41,7 +41,6 @@ import androidx.test.filters.SmallTest; import com.android.internal.statusbar.IStatusBarService; import com.android.systemui.SysuiTestCase; import com.android.systemui.statusbar.RankingBuilder; -import com.android.systemui.statusbar.notification.SectionClassifier; import com.android.systemui.statusbar.notification.collection.GroupEntry; import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder; import com.android.systemui.statusbar.notification.collection.ListEntry; @@ -56,6 +55,7 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.OnBefo import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; +import com.android.systemui.statusbar.notification.collection.provider.SectionStyleProvider; import com.android.systemui.statusbar.notification.collection.render.NotifViewBarn; import com.android.systemui.statusbar.notification.row.NotifInflationErrorManager; @@ -96,9 +96,9 @@ public class PreparationCoordinatorTest extends SysuiTestCase { @Mock private IStatusBarService mService; @Mock private BindEventManagerImpl mBindEventManagerImpl; @Spy private FakeNotifInflater mNotifInflater = new FakeNotifInflater(); - private final SectionClassifier mSectionClassifier = new SectionClassifier(); + private final SectionStyleProvider mSectionStyleProvider = new SectionStyleProvider(); private final NotifUiAdjustmentProvider mAdjustmentProvider = - new NotifUiAdjustmentProvider(mSectionClassifier); + new NotifUiAdjustmentProvider(mSectionStyleProvider); @NonNull private NotificationEntryBuilder getNotificationEntryBuilder() { @@ -487,7 +487,7 @@ public class PreparationCoordinatorTest extends SysuiTestCase { private static final int TEST_MAX_GROUP_DELAY = 100; private void setSectionIsLowPriority(boolean minimized) { - mSectionClassifier.setMinimizedSections(minimized + mSectionStyleProvider.setMinimizedSections(minimized ? Collections.singleton(mNotifSection.getSectioner()) : Collections.emptyList()); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java index f4d8405a796e..ff08bc38c944 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java @@ -40,7 +40,6 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.RankingBuilder; import com.android.systemui.statusbar.SbnBuilder; -import com.android.systemui.statusbar.notification.SectionClassifier; import com.android.systemui.statusbar.notification.collection.ListEntry; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; @@ -48,6 +47,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntryB import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner; import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider; +import com.android.systemui.statusbar.notification.collection.provider.SectionStyleProvider; import com.android.systemui.statusbar.notification.collection.render.NodeController; import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController; @@ -68,7 +68,7 @@ public class RankingCoordinatorTest extends SysuiTestCase { @Mock private StatusBarStateController mStatusBarStateController; @Mock private HighPriorityProvider mHighPriorityProvider; - @Mock private SectionClassifier mSectionClassifier; + @Mock private SectionStyleProvider mSectionStyleProvider; @Mock private NotifPipeline mNotifPipeline; @Mock private NodeController mAlertingHeaderController; @Mock private NodeController mSilentNodeController; @@ -92,7 +92,7 @@ public class RankingCoordinatorTest extends SysuiTestCase { mRankingCoordinator = new RankingCoordinator( mStatusBarStateController, mHighPriorityProvider, - mSectionClassifier, + mSectionStyleProvider, mAlertingHeaderController, mSilentHeaderController, mSilentNodeController); @@ -100,7 +100,7 @@ public class RankingCoordinatorTest extends SysuiTestCase { mEntry.setRanking(getRankingForUnfilteredNotif().build()); mRankingCoordinator.attach(mNotifPipeline); - verify(mSectionClassifier).setMinimizedSections(any()); + verify(mSectionStyleProvider).setMinimizedSections(any()); verify(mNotifPipeline, times(2)).addPreGroupFilter(mNotifFilterCaptor.capture()); mCapturedSuspendedFilter = mNotifFilterCaptor.getAllValues().get(0); mCapturedDozingFilter = mNotifFilterCaptor.getAllValues().get(1); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinatorTest.kt index 447ba1510e13..40859d0e6304 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinatorTest.kt @@ -21,13 +21,13 @@ import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.statusbar.notification.AssistantFeedbackController import com.android.systemui.statusbar.notification.FeedbackIcon -import com.android.systemui.statusbar.notification.SectionClassifier import com.android.systemui.statusbar.notification.collection.NotifPipeline import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection import com.android.systemui.statusbar.notification.collection.listbuilder.OnAfterRenderEntryListener import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener +import com.android.systemui.statusbar.notification.collection.provider.SectionStyleProvider import com.android.systemui.statusbar.notification.collection.render.NotifRowController import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.eq @@ -53,7 +53,7 @@ class RowAppearanceCoordinatorTest : SysuiTestCase() { @Mock private lateinit var pipeline: NotifPipeline @Mock private lateinit var assistantFeedbackController: AssistantFeedbackController - @Mock private lateinit var sectionClassifier: SectionClassifier + @Mock private lateinit var sectionStyleProvider: SectionStyleProvider @Mock private lateinit var section1: NotifSection @Mock private lateinit var section2: NotifSection @@ -66,7 +66,7 @@ class RowAppearanceCoordinatorTest : SysuiTestCase() { coordinator = RowAppearanceCoordinator( mContext, assistantFeedbackController, - sectionClassifier + sectionStyleProvider ) coordinator.attach(pipeline) beforeRenderListListener = withArgCaptor { @@ -82,8 +82,8 @@ class RowAppearanceCoordinatorTest : SysuiTestCase() { @Test fun testSetSystemExpandedOnlyOnFirst() { - whenever(sectionClassifier.isMinimizedSection(eq(section1))).thenReturn(false) - whenever(sectionClassifier.isMinimizedSection(eq(section1))).thenReturn(false) + whenever(sectionStyleProvider.isMinimizedSection(eq(section1))).thenReturn(false) + whenever(sectionStyleProvider.isMinimizedSection(eq(section1))).thenReturn(false) beforeRenderListListener.onBeforeRenderList(listOf(entry1, entry2)) afterRenderEntryListener.onAfterRenderEntry(entry1, controller1) verify(controller1).setSystemExpanded(eq(true)) @@ -93,8 +93,8 @@ class RowAppearanceCoordinatorTest : SysuiTestCase() { @Test fun testSetSystemExpandedNeverIfMinimized() { - whenever(sectionClassifier.isMinimizedSection(eq(section1))).thenReturn(true) - whenever(sectionClassifier.isMinimizedSection(eq(section1))).thenReturn(true) + whenever(sectionStyleProvider.isMinimizedSection(eq(section1))).thenReturn(true) + whenever(sectionStyleProvider.isMinimizedSection(eq(section1))).thenReturn(true) beforeRenderListListener.onBeforeRenderList(listOf(entry1, entry2)) afterRenderEntryListener.onAfterRenderEntry(entry1, controller1) verify(controller1).setSystemExpanded(eq(false)) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderTest.kt index 0e1865861cae..ff601938d544 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderTest.kt @@ -19,7 +19,6 @@ package com.android.systemui.statusbar.notification.collection.render import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager -import com.android.systemui.statusbar.notification.SectionHeaderVisibilityProvider import com.android.systemui.statusbar.notification.collection.GroupEntry import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder import com.android.systemui.statusbar.notification.collection.ListEntry @@ -28,6 +27,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntryB import com.android.systemui.statusbar.notification.collection.getAttachState import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner +import com.android.systemui.statusbar.notification.collection.provider.SectionHeaderVisibilityProvider import com.android.systemui.statusbar.notification.stack.BUCKET_ALERTING import com.android.systemui.statusbar.notification.stack.BUCKET_PEOPLE import com.android.systemui.statusbar.notification.stack.BUCKET_SILENT diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java index 1ecb09bc8514..3d57f66c5dc4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java @@ -144,10 +144,9 @@ public class NotificationTestHelper { mock(KeyguardBypassController.class), mock(NotificationGroupManagerLegacy.class), mock(VisualStabilityProvider.class), - mock(ConfigurationControllerImpl.class) + mock(ConfigurationControllerImpl.class), + new Handler(mTestLooper.getLooper()) ); - mHeadsUpManager.mHandler.removeCallbacksAndMessages(null); - mHeadsUpManager.mHandler = new Handler(mTestLooper.getLooper()); mGroupMembershipManager.setHeadsUpManager(mHeadsUpManager); mIconManager = new IconManager( mock(CommonNotifCollection.class), diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java index 7a92b96f40db..077f6bfc5f31 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java @@ -64,6 +64,7 @@ import com.android.systemui.statusbar.notification.row.FooterView; import com.android.systemui.statusbar.phone.CentralSurfaces; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.ShadeController; +import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController; import org.junit.Assert; @@ -104,6 +105,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Mock private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; @Mock private NotificationShelf mNotificationShelf; @Mock private NotificationStackSizeCalculator mNotificationStackSizeCalculator; + @Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; @Before @UiThreadTest @@ -111,7 +113,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { allowTestableLooperAsMainThread(); // Interact with real instance of AmbientState. - mAmbientState = new AmbientState(mContext, mNotificationSectionsManager, mBypassController); + mAmbientState = new AmbientState(mContext, mNotificationSectionsManager, mBypassController, + mStatusBarKeyguardViewManager); // Inject dependencies before initializing the layout mDependency.injectTestDependency(SysuiStatusBarStateController.class, mBarState); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt index f864fb0281f8..1f90d0cf9494 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt @@ -9,6 +9,7 @@ import com.android.systemui.statusbar.EmptyShadeView import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.BypassController import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.SectionProvider +import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test @@ -22,10 +23,14 @@ class StackScrollAlgorithmTest : SysuiTestCase() { private val stackScrollAlgorithm = StackScrollAlgorithm(context, hostView) private val expandableViewState = ExpandableViewState() private val notificationRow = mock(ExpandableNotificationRow::class.java) + private val mStatusBarKeyguardViewManager = mock(StatusBarKeyguardViewManager::class.java) + private val ambientState = AmbientState( - context, - SectionProvider { _, _ -> false }, - BypassController { false }) + context, + SectionProvider { _, _ -> false }, + BypassController { false }, + mStatusBarKeyguardViewManager + ) private val testableResources = mContext.orCreateTestableResources diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java index db5741c90ebc..b8c8b5f26f0f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java @@ -23,6 +23,7 @@ import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.when; import android.content.Context; +import android.os.Handler; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.view.View; @@ -76,7 +77,8 @@ public class HeadsUpManagerPhoneTest extends AlertingNotificationManagerTest { VisualStabilityProvider visualStabilityProvider, StatusBarStateController statusBarStateController, KeyguardBypassController keyguardBypassController, - ConfigurationController configurationController + ConfigurationController configurationController, + Handler handler ) { super( context, @@ -85,7 +87,8 @@ public class HeadsUpManagerPhoneTest extends AlertingNotificationManagerTest { keyguardBypassController, groupManager, visualStabilityProvider, - configurationController + configurationController, + handler ); mMinimumDisplayTime = TEST_MINIMUM_DISPLAY_TIME; mAutoDismissNotificationDecay = TEST_AUTO_DISMISS_TIME; @@ -105,6 +108,8 @@ public class HeadsUpManagerPhoneTest extends AlertingNotificationManagerTest { when(mVSProvider.isReorderingAllowed()).thenReturn(true); mDependency.injectMockDependency(NotificationShadeWindowController.class); mDependency.injectMockDependency(ConfigurationController.class); + super.setUp(); + mHeadsUpManager = new TestableHeadsUpManagerPhone( mContext, mHeadsUpManagerLogger, @@ -112,11 +117,9 @@ public class HeadsUpManagerPhoneTest extends AlertingNotificationManagerTest { mVSProvider, mStatusBarStateController, mBypassController, - mConfigurationController + mConfigurationController, + mTestHandler ); - super.setUp(); - mHeadsUpManager.mHandler.removeCallbacksAndMessages(null); - mHeadsUpManager.mHandler = mTestHandler; } @After diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java index 7070bc19db62..56dfb0cee520 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java @@ -30,6 +30,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.Notification; +import android.os.Handler; import android.service.notification.StatusBarNotification; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; @@ -51,7 +52,6 @@ import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.HeadsUpManagerLogger; import com.android.wm.shell.bubbles.Bubbles; -import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -89,7 +89,8 @@ public class NotificationGroupAlertTransferHelperTest extends SysuiTestCase { @Before public void setup() { MockitoAnnotations.initMocks(this); - mHeadsUpManager = new HeadsUpManager(mContext, mock(HeadsUpManagerLogger.class)) {}; + mHeadsUpManager = new HeadsUpManager(mContext, mock(HeadsUpManagerLogger.class), + mock(Handler.class)) {}; when(mNotificationEntryManager.getPendingNotificationsIterator()) .thenReturn(mPendingEntries.values()); @@ -114,11 +115,6 @@ public class NotificationGroupAlertTransferHelperTest extends SysuiTestCase { mHeadsUpManager.addListener(mGroupAlertTransferHelper); } - @After - public void tearDown() { - mHeadsUpManager.mHandler.removeCallbacksAndMessages(null); - } - private void mockHasHeadsUpContentView(NotificationEntry entry, boolean hasHeadsUpContentView) { RowContentBindParams params = new RowContentBindParams(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java index ab7dd2a5b507..dce520c0973d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java @@ -1238,7 +1238,7 @@ public class ScrimControllerTest extends SysuiTestCase { @Test public void expansionNotificationAlpha_shadeLocked_bouncerActive_usesBouncerInterpolator() { - when(mStatusBarKeyguardViewManager.bouncerIsInTransit()).thenReturn(true); + when(mStatusBarKeyguardViewManager.isBouncerInTransit()).thenReturn(true); mScrimController.transitionTo(ScrimState.SHADE_LOCKED); @@ -1254,7 +1254,7 @@ public class ScrimControllerTest extends SysuiTestCase { @Test public void expansionNotificationAlpha_shadeLocked_bouncerNotActive_usesShadeInterpolator() { - when(mStatusBarKeyguardViewManager.bouncerIsInTransit()).thenReturn(false); + when(mStatusBarKeyguardViewManager.isBouncerInTransit()).thenReturn(false); mScrimController.transitionTo(ScrimState.SHADE_LOCKED); @@ -1291,7 +1291,7 @@ public class ScrimControllerTest extends SysuiTestCase { @Test public void notificationAlpha_unnocclusionAnimating_bouncerNotActive_usesKeyguardNotifAlpha() { - when(mStatusBarKeyguardViewManager.bouncerIsInTransit()).thenReturn(false); + when(mStatusBarKeyguardViewManager.isBouncerInTransit()).thenReturn(false); mScrimController.transitionTo(ScrimState.KEYGUARD); mScrimController.setUnocclusionAnimationRunning(true); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java index 90cbf540004e..2b018727eb98 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java @@ -438,12 +438,12 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase { } @Test - public void testBouncerIsInTransit() { + public void testIsBouncerInTransit() { when(mBouncer.inTransit()).thenReturn(true); - Truth.assertThat(mStatusBarKeyguardViewManager.bouncerIsInTransit()).isTrue(); + Truth.assertThat(mStatusBarKeyguardViewManager.isBouncerInTransit()).isTrue(); when(mBouncer.inTransit()).thenReturn(false); - Truth.assertThat(mStatusBarKeyguardViewManager.bouncerIsInTransit()).isFalse(); + Truth.assertThat(mStatusBarKeyguardViewManager.isBouncerInTransit()).isFalse(); mBouncer = null; - Truth.assertThat(mStatusBarKeyguardViewManager.bouncerIsInTransit()).isFalse(); + Truth.assertThat(mStatusBarKeyguardViewManager.isBouncerInTransit()).isFalse(); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java index 98397fb01b6b..7e4862edf7f3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java @@ -48,7 +48,6 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.DisableFlagsLogger; import com.android.systemui.statusbar.OperatorNameViewController; -import com.android.systemui.statusbar.connectivity.NetworkController; import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler; import com.android.systemui.statusbar.phone.HeadsUpAppearanceController; import com.android.systemui.statusbar.phone.NotificationIconAreaController; @@ -84,7 +83,6 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { private StatusBarLocationPublisher mLocationPublisher; // Set in instantiate() private StatusBarIconController mStatusBarIconController; - private NetworkController mNetworkController; private KeyguardStateController mKeyguardStateController; private final CommandQueue mCommandQueue = mock(CommandQueue.class); @@ -352,7 +350,6 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { mAnimationScheduler = mock(SystemStatusAnimationScheduler.class); mLocationPublisher = mock(StatusBarLocationPublisher.class); mStatusBarIconController = mock(StatusBarIconController.class); - mNetworkController = mock(NetworkController.class); mStatusBarStateController = mock(StatusBarStateController.class); mKeyguardStateController = mock(KeyguardStateController.class); mOperatorNameViewController = mock(OperatorNameViewController.class); @@ -374,7 +371,6 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { mStatusBarHideIconsForBouncerManager, mKeyguardStateController, mNotificationPanelViewController, - mNetworkController, mStatusBarStateController, mCommandQueue, mCarrierConfigTracker, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java index 424a40058997..f39d6875cffc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java @@ -36,6 +36,7 @@ import android.app.PendingIntent; import android.app.Person; import android.content.Context; import android.content.Intent; +import android.os.Handler; import android.service.notification.StatusBarNotification; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; @@ -73,8 +74,8 @@ public class HeadsUpManagerTest extends AlertingNotificationManagerTest { @Mock private HeadsUpManagerLogger mLogger; private final class TestableHeadsUpManager extends HeadsUpManager { - TestableHeadsUpManager(Context context, HeadsUpManagerLogger logger) { - super(context, logger); + TestableHeadsUpManager(Context context, HeadsUpManagerLogger logger, Handler handler) { + super(context, logger, handler); mMinimumDisplayTime = TEST_MINIMUM_DISPLAY_TIME; mAutoDismissNotificationDecay = TEST_AUTO_DISMISS_TIME; } @@ -91,10 +92,9 @@ public class HeadsUpManagerTest extends AlertingNotificationManagerTest { mDependency.injectTestDependency(UiEventLogger.class, mUiEventLoggerFake); when(mEntry.getSbn()).thenReturn(mSbn); when(mSbn.getNotification()).thenReturn(mNotification); - mHeadsUpManager = new TestableHeadsUpManager(mContext, mLogger); + super.setUp(); - mHeadsUpManager.mHandler.removeCallbacksAndMessages(null); - mHeadsUpManager.mHandler = mTestHandler; + mHeadsUpManager = new TestableHeadsUpManager(mContext, mLogger, mTestHandler); } @After diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt index e3d2a2951c97..152815f2d47e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.policy import android.app.IActivityManager +import android.app.NotificationManager import android.app.admin.DevicePolicyManager import android.content.Context import android.content.DialogInterface @@ -37,7 +38,9 @@ import com.android.internal.jank.InteractionJankMonitor import com.android.internal.logging.testing.UiEventLoggerFake import com.android.internal.util.LatencyTracker import com.android.internal.util.UserIcons +import com.android.systemui.GuestResetOrExitSessionReceiver import com.android.systemui.GuestResumeSessionReceiver +import com.android.systemui.GuestSessionNotification import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.animation.DialogLaunchAnimator @@ -99,6 +102,11 @@ class UserSwitcherControllerTest : SysuiTestCase() { @Mock private lateinit var threadedRenderer: ThreadedRenderer @Mock private lateinit var dialogLaunchAnimator: DialogLaunchAnimator @Mock private lateinit var globalSettings: GlobalSettings + @Mock private lateinit var guestSessionNotification: GuestSessionNotification + @Mock private lateinit var guestResetOrExitSessionReceiver: GuestResetOrExitSessionReceiver + private lateinit var resetSessionDialogFactory: + GuestResumeSessionReceiver.ResetSessionDialog.Factory + private lateinit var guestResumeSessionReceiver: GuestResumeSessionReceiver private lateinit var testableLooper: TestableLooper private lateinit var bgExecutor: FakeExecutor private lateinit var longRunningExecutor: FakeExecutor @@ -130,9 +138,28 @@ class UserSwitcherControllerTest : SysuiTestCase() { com.android.internal.R.bool.config_guestUserAutoCreated, false) mContext.addMockSystemService(Context.FACE_SERVICE, mock(FaceManager::class.java)) + mContext.addMockSystemService(Context.NOTIFICATION_SERVICE, + mock(NotificationManager::class.java)) mContext.addMockSystemService(Context.FINGERPRINT_SERVICE, mock(FingerprintManager::class.java)) + resetSessionDialogFactory = object : GuestResumeSessionReceiver.ResetSessionDialog.Factory { + override fun create(userId: Int): GuestResumeSessionReceiver.ResetSessionDialog { + return GuestResumeSessionReceiver.ResetSessionDialog( + mContext, + mock(UserSwitcherController::class.java), + uiEventLogger, + userId + ) + } + } + + guestResumeSessionReceiver = GuestResumeSessionReceiver(userTracker, + secureSettings, + broadcastDispatcher, + guestSessionNotification, + resetSessionDialogFactory) + `when`(userManager.canAddMoreUsers(eq(UserManager.USER_TYPE_FULL_SECONDARY))) .thenReturn(true) `when`(notificationShadeWindowView.context).thenReturn(context) @@ -195,7 +222,9 @@ class UserSwitcherControllerTest : SysuiTestCase() { interactionJankMonitor, latencyTracker, dumpManager, - dialogLaunchAnimator) + dialogLaunchAnimator, + guestResumeSessionReceiver, + guestResetOrExitSessionReceiver) userSwitcherController.init(notificationShadeWindowView) } @@ -285,7 +314,10 @@ class UserSwitcherControllerTest : SysuiTestCase() { .getButton(DialogInterface.BUTTON_POSITIVE).performClick() testableLooper.processAllMessages() assertEquals(1, uiEventLogger.numLogs()) - assertEquals(QSUserSwitcherEvent.QS_USER_GUEST_REMOVE.id, uiEventLogger.eventId(0)) + assertTrue( + QSUserSwitcherEvent.QS_USER_GUEST_REMOVE.id == uiEventLogger.eventId(0) || + QSUserSwitcherEvent.QS_USER_SWITCH.id == uiEventLogger.eventId(0) + ) } @Test @@ -347,7 +379,7 @@ class UserSwitcherControllerTest : SysuiTestCase() { userSwitcherController.onUserListItemClicked(currentGuestUserRecord, null) assertNotNull(userSwitcherController.mExitGuestDialog) userSwitcherController.mExitGuestDialog - .getButton(DialogInterface.BUTTON_NEGATIVE).performClick() + .getButton(DialogInterface.BUTTON_NEUTRAL).performClick() testableLooper.processAllMessages() assertEquals(0, uiEventLogger.numLogs()) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/condition/ConditionMonitorTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/condition/ConditionMonitorTest.java index 5118637ea710..758961658f2a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/util/condition/ConditionMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/util/condition/ConditionMonitorTest.java @@ -65,7 +65,7 @@ public class ConditionMonitorTest extends SysuiTestCase { mCondition3 = spy(new FakeCondition()); mConditions = new HashSet<>(Arrays.asList(mCondition1, mCondition2, mCondition3)); - mConditionMonitor = new Monitor(mExecutor, mConditions, null /*callbacks*/); + mConditionMonitor = new Monitor(mExecutor, mConditions); } @Test @@ -76,8 +76,10 @@ public class ConditionMonitorTest extends SysuiTestCase { final Monitor monitor = new Monitor( mExecutor, - new HashSet<>(Arrays.asList(overridingCondition, regularCondition)), - new HashSet<>(Arrays.asList(callback))); + new HashSet<>(Arrays.asList(overridingCondition, regularCondition))); + + monitor.addCallback(callback); + mExecutor.runAllReady(); when(overridingCondition.isOverridingCondition()).thenReturn(true); when(overridingCondition.isConditionMet()).thenReturn(true); @@ -123,8 +125,9 @@ public class ConditionMonitorTest extends SysuiTestCase { final Monitor monitor = new Monitor( mExecutor, new HashSet<>(Arrays.asList(overridingCondition, overridingCondition2, - regularCondition)), - new HashSet<>(Arrays.asList(callback))); + regularCondition))); + monitor.addCallback(callback); + mExecutor.runAllReady(); when(overridingCondition.isOverridingCondition()).thenReturn(true); when(overridingCondition.isConditionMet()).thenReturn(true); @@ -174,8 +177,8 @@ public class ConditionMonitorTest extends SysuiTestCase { mock(Monitor.Callback.class); final Condition condition = mock(Condition.class); when(condition.isConditionMet()).thenReturn(true); - final Monitor monitor = new Monitor(mExecutor, new HashSet<>(Arrays.asList(condition)), - new HashSet<>(Arrays.asList(callback1))); + final Monitor monitor = new Monitor(mExecutor, new HashSet<>(Arrays.asList(condition))); + monitor.addCallback(callback1); final Monitor.Callback callback2 = mock(Monitor.Callback.class); @@ -186,7 +189,7 @@ public class ConditionMonitorTest extends SysuiTestCase { @Test public void addCallback_noConditions_reportAllConditionsMet() { - final Monitor monitor = new Monitor(mExecutor, new HashSet<>(), null /*callbacks*/); + final Monitor monitor = new Monitor(mExecutor, new HashSet<>()); final Monitor.Callback callback = mock(Monitor.Callback.class); monitor.addCallback(callback); @@ -196,7 +199,7 @@ public class ConditionMonitorTest extends SysuiTestCase { @Test public void addCallback_withMultipleInstancesOfTheSameCallback_registerOnlyOne() { - final Monitor monitor = new Monitor(mExecutor, new HashSet<>(), null /*callbacks*/); + final Monitor monitor = new Monitor(mExecutor, new HashSet<>()); final Monitor.Callback callback = mock(Monitor.Callback.class); // Adds the same instance multiple times. @@ -212,8 +215,7 @@ public class ConditionMonitorTest extends SysuiTestCase { @Test public void removeCallback_shouldNoLongerReceiveUpdate() { final Condition condition = mock(Condition.class); - final Monitor monitor = new Monitor(mExecutor, new HashSet<>(Arrays.asList(condition)), - null); + final Monitor monitor = new Monitor(mExecutor, new HashSet<>(Arrays.asList(condition))); final Monitor.Callback callback = mock(Monitor.Callback.class); monitor.addCallback(callback); diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeNetworkController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeNetworkController.java index 33ef9cf7a9c5..1baac84d5ca6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeNetworkController.java +++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeNetworkController.java @@ -46,11 +46,6 @@ public class FakeNetworkController extends BaseLeakChecker<SignalCallback> } @Override - public boolean hasEmergencyCryptKeeperText() { - return false; - } - - @Override public boolean isRadioOn() { return false; } diff --git a/packages/SystemUI/tools/lint/baseline.xml b/packages/SystemUI/tools/lint/baseline.xml index 9a2e3207a6f4..301c9b831c3b 100644 --- a/packages/SystemUI/tools/lint/baseline.xml +++ b/packages/SystemUI/tools/lint/baseline.xml @@ -337,17 +337,6 @@ <issue id="Deprecated" message="`android:singleLine` is deprecated: Use `maxLines="1"` instead" - errorLine1=" android:singleLine="true"" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="res/layout/emergency_cryptkeeper_text.xml" - line="25" - column="9"/> - </issue> - - <issue - id="Deprecated" - message="`android:singleLine` is deprecated: Use `maxLines="1"` instead" errorLine1=" android:singleLine="true"" errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> <location @@ -88997,17 +88986,6 @@ errorLine1=" android:paddingStart="6dp"" errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> <location - file="res/layout/emergency_cryptkeeper_text.xml" - line="24" - column="9"/> - </issue> - - <issue - id="RtlSymmetry" - message="When you define `paddingStart` you should probably also define `paddingEnd` for right-to-left symmetry" - errorLine1=" android:paddingStart="6dp"" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> - <location file="res/layout/heads_up_status_bar_layout.xml" line="43" column="9"/> diff --git a/packages/VpnDialogs/res/values-or/strings.xml b/packages/VpnDialogs/res/values-or/strings.xml index 0604b47cdb50..4c5c2591986f 100644 --- a/packages/VpnDialogs/res/values-or/strings.xml +++ b/packages/VpnDialogs/res/values-or/strings.xml @@ -29,7 +29,7 @@ <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> ସବୁ ସମୟରେ କନେକ୍ଟ ହୋଇ ରହିବା ପାଇଁ ସେଟଅପ୍ କରାଯାଇଛି। ଆପଣଙ୍କ ଫୋନ୍, <xliff:g id="VPN_APP_1">%1$s</xliff:g> ସହ କନେକ୍ଟ ନହେବା ପର୍ଯ୍ୟନ୍ତ ଏକ ପବ୍ଲିକ୍ ନେଟ୍ୱର୍କ ବ୍ୟବହାର କରିବ।"</string> <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"<xliff:g id="VPN_APP">%1$s</xliff:g> ସବୁ ସମୟରେ କନେକ୍ଟ ହୋଇରହିବାକୁ ସେଟଅପ୍ କରାଯାଇଛି, କିନ୍ତୁ ଏହା ବର୍ତ୍ତମାନ କନେକ୍ଟ କରିପାରୁ ନାହିଁ। VPN ପୁଣି କନେକ୍ଟ ନହେବା ପର୍ଯ୍ୟନ୍ତ ଆପଣଙ୍କର କୌଣସି କନେକ୍ସନ୍ ରହିବନାହିଁ।"</string> <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> - <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"VPN ସେଟିଂସ୍ ବଦଳାନ୍ତୁ"</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"VPN ସେଟିଂସ ବଦଳାନ୍ତୁ"</string> <string name="configure" msgid="4905518375574791375">"କନଫିଗର୍ କରନ୍ତୁ"</string> <string name="disconnect" msgid="971412338304200056">"ବିଚ୍ଛିନ୍ନ କରନ୍ତୁ"</string> <string name="open_app" msgid="3717639178595958667">"ଆପ୍ ଖୋଲନ୍ତୁ"</string> diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto index dfa34bb50805..0a4ecb227548 100644 --- a/proto/src/system_messages.proto +++ b/proto/src/system_messages.proto @@ -286,10 +286,18 @@ message SystemMessage { // Package: android NOTE_MTE_OVERRIDE_ENABLED = 69; + // Notify the user that this is a guest session with information + // about first login and ephemeral state + // Package: android + NOTE_GUEST_SESSION = 70; + // Inform the user of notification permissions changes. // Package: android NOTE_REVIEW_NOTIFICATION_PERMISSIONS = 71; + // Notify the user to setup their dock + NOTE_SETUP_DOCK = 72; + // ADD_NEW_IDS_ABOVE_THIS_LINE // Legacy IDs with arbitrary values appear below // Legacy IDs existed as stable non-conflicting constants prior to the O release diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java index e30639cf416a..cb71a4089353 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java @@ -557,12 +557,17 @@ public class AccessibilityWindowManager { shouldClearAccessibilityFocus = mAccessibilityFocusedWindowId != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID; } + + boolean hasWindowIgnore = false; if (windowCount > 0) { for (int i = 0; i < windowCount; i++) { final WindowInfo windowInfo = windows.get(i); final AccessibilityWindowInfo window; if (mTrackingWindows) { window = populateReportedWindowLocked(userId, windowInfo); + if (window == null) { + hasWindowIgnore = true; + } } else { window = null; } @@ -591,6 +596,13 @@ public class AccessibilityWindowManager { } } final int accessibilityWindowCount = mWindows.size(); + // Re-order the window layer of all windows in the windows list because there's + // window not been added into the windows list. + if (hasWindowIgnore) { + for (int i = 0; i < accessibilityWindowCount; i++) { + mWindows.get(i).setLayer(accessibilityWindowCount - 1 - i); + } + } if (isTopFocusedDisplay) { if (mTouchInteractionInProgress && activeWindowGone) { mActiveWindowId = mTopFocusedWindowId; diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java index 2cf0e3e54326..9a257e54cf41 100644 --- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java +++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java @@ -45,6 +45,7 @@ import android.content.Context; import android.graphics.Region; import android.os.Handler; import android.util.DisplayMetrics; +import android.util.Log; import android.util.Slog; import android.view.Display; import android.view.InputDevice; @@ -84,12 +85,14 @@ import java.util.List; public class TouchExplorer extends BaseEventStreamTransformation implements GestureManifold.Listener { - static final boolean DEBUG = false; private static final long LOGGING_FLAGS = FLAGS_GESTURE | FLAGS_INPUT_FILTER; // Tag for logging received events. private static final String LOG_TAG = "TouchExplorer"; + // To enable these logs, run: 'adb shell setprop log.tag.TouchExplorer DEBUG' (requires restart) + static final boolean DEBUG = Log.isLoggable(LOG_TAG, Log.DEBUG); + // The maximum of the cosine between the vectors of two moving // pointers so they can be considered moving in the same direction. private static final float MAX_DRAGGING_ANGLE_COS = 0.525321989f; // cos(pi/4) diff --git a/services/autofill/java/com/android/server/autofill/ClientSuggestionsSession.java b/services/autofill/java/com/android/server/autofill/ClientSuggestionsSession.java new file mode 100644 index 000000000000..715697d82cad --- /dev/null +++ b/services/autofill/java/com/android/server/autofill/ClientSuggestionsSession.java @@ -0,0 +1,293 @@ +/* + * 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.autofill; + +import static android.service.autofill.FillRequest.INVALID_REQUEST_ID; + +import static com.android.server.autofill.Helper.sVerbose; + +import android.annotation.Nullable; +import android.annotation.UserIdInt; +import android.app.AppGlobals; +import android.content.ComponentName; +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.os.ICancellationSignal; +import android.os.RemoteException; +import android.service.autofill.Dataset; +import android.service.autofill.FillResponse; +import android.service.autofill.IFillCallback; +import android.service.autofill.SaveInfo; +import android.text.TextUtils; +import android.text.format.DateUtils; +import android.util.Slog; +import android.view.autofill.AutofillId; +import android.view.autofill.IAutoFillManagerClient; +import android.view.inputmethod.InlineSuggestionsRequest; + +import com.android.internal.annotations.GuardedBy; +import com.android.internal.infra.AndroidFuture; + +import java.util.List; +import java.util.concurrent.CancellationException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicReference; + +/** + * Maintains a client suggestions session with the + * {@link android.view.autofill.AutofillRequestCallback} through the {@link IAutoFillManagerClient}. + * + */ +final class ClientSuggestionsSession { + + private static final String TAG = "ClientSuggestionsSession"; + private static final long TIMEOUT_REMOTE_REQUEST_MILLIS = 15 * DateUtils.SECOND_IN_MILLIS; + + private final int mSessionId; + private final IAutoFillManagerClient mClient; + private final Handler mHandler; + private final ComponentName mComponentName; + + private final RemoteFillService.FillServiceCallbacks mCallbacks; + + private final Object mLock = new Object(); + @GuardedBy("mLock") + private AndroidFuture<FillResponse> mPendingFillRequest; + @GuardedBy("mLock") + private int mPendingFillRequestId = INVALID_REQUEST_ID; + + ClientSuggestionsSession(int sessionId, IAutoFillManagerClient client, Handler handler, + ComponentName componentName, RemoteFillService.FillServiceCallbacks callbacks) { + mSessionId = sessionId; + mClient = client; + mHandler = handler; + mComponentName = componentName; + mCallbacks = callbacks; + } + + void onFillRequest(int requestId, InlineSuggestionsRequest inlineRequest, int flags) { + final AtomicReference<ICancellationSignal> cancellationSink = new AtomicReference<>(); + final AtomicReference<AndroidFuture<FillResponse>> futureRef = new AtomicReference<>(); + final AndroidFuture<FillResponse> fillRequest = new AndroidFuture<>(); + + mHandler.post(() -> { + if (sVerbose) { + Slog.v(TAG, "calling onFillRequest() for id=" + requestId); + } + + try { + mClient.requestFillFromClient(requestId, inlineRequest, + new FillCallbackImpl(fillRequest, futureRef, cancellationSink)); + } catch (RemoteException e) { + fillRequest.completeExceptionally(e); + } + }); + + fillRequest.orTimeout(TIMEOUT_REMOTE_REQUEST_MILLIS, TimeUnit.MILLISECONDS); + futureRef.set(fillRequest); + + synchronized (mLock) { + mPendingFillRequest = fillRequest; + mPendingFillRequestId = requestId; + } + + fillRequest.whenComplete((res, err) -> mHandler.post(() -> { + synchronized (mLock) { + mPendingFillRequest = null; + mPendingFillRequestId = INVALID_REQUEST_ID; + } + if (err == null) { + processAutofillId(res); + mCallbacks.onFillRequestSuccess(requestId, res, + mComponentName.getPackageName(), flags); + } else { + Slog.e(TAG, "Error calling on client fill request", err); + if (err instanceof TimeoutException) { + dispatchCancellationSignal(cancellationSink.get()); + mCallbacks.onFillRequestTimeout(requestId); + } else if (err instanceof CancellationException) { + dispatchCancellationSignal(cancellationSink.get()); + } else { + mCallbacks.onFillRequestFailure(requestId, err.getMessage()); + } + } + })); + } + + /** + * Gets the application info for the component. + */ + @Nullable + static ApplicationInfo getAppInfo(ComponentName comp, @UserIdInt int userId) { + try { + ApplicationInfo si = AppGlobals.getPackageManager().getApplicationInfo( + comp.getPackageName(), + PackageManager.GET_META_DATA, + userId); + if (si != null) { + return si; + } + } catch (RemoteException e) { + } + return null; + } + + /** + * Gets the user-visible name of the application. + */ + @Nullable + @GuardedBy("mLock") + static CharSequence getAppLabelLocked(Context context, ApplicationInfo appInfo) { + return appInfo == null ? null : appInfo.loadSafeLabel( + context.getPackageManager(), 0 /* do not ellipsize */, + TextUtils.SAFE_STRING_FLAG_FIRST_LINE | TextUtils.SAFE_STRING_FLAG_TRIM); + } + + /** + * Gets the user-visible icon of the application. + */ + @Nullable + @GuardedBy("mLock") + static Drawable getAppIconLocked(Context context, ApplicationInfo appInfo) { + return appInfo == null ? null : appInfo.loadIcon(context.getPackageManager()); + } + + int cancelCurrentRequest() { + synchronized (mLock) { + return mPendingFillRequest != null && mPendingFillRequest.cancel(false) + ? mPendingFillRequestId + : INVALID_REQUEST_ID; + } + } + + /** + * The {@link AutofillId} which the client gets from its view is not contain the session id, + * but Autofill framework is using the {@link AutofillId} with a session id. So before using + * those ids in the Autofill framework, applies the current session id. + * + * @param res which response need to apply for a session id + */ + private void processAutofillId(FillResponse res) { + if (res == null) { + return; + } + + final List<Dataset> datasets = res.getDatasets(); + if (datasets != null && !datasets.isEmpty()) { + for (int i = 0; i < datasets.size(); i++) { + final Dataset dataset = datasets.get(i); + if (dataset != null) { + applySessionId(dataset.getFieldIds()); + } + } + } + + final SaveInfo saveInfo = res.getSaveInfo(); + if (saveInfo != null) { + applySessionId(saveInfo.getOptionalIds()); + applySessionId(saveInfo.getRequiredIds()); + applySessionId(saveInfo.getSanitizerValues()); + applySessionId(saveInfo.getTriggerId()); + } + } + + private void applySessionId(List<AutofillId> ids) { + if (ids == null || ids.isEmpty()) { + return; + } + + for (int i = 0; i < ids.size(); i++) { + applySessionId(ids.get(i)); + } + } + + private void applySessionId(AutofillId[][] ids) { + if (ids == null) { + return; + } + for (int i = 0; i < ids.length; i++) { + applySessionId(ids[i]); + } + } + + private void applySessionId(AutofillId[] ids) { + if (ids == null) { + return; + } + for (int i = 0; i < ids.length; i++) { + applySessionId(ids[i]); + } + } + + private void applySessionId(AutofillId id) { + if (id == null) { + return; + } + id.setSessionId(mSessionId); + } + + private void dispatchCancellationSignal(@Nullable ICancellationSignal signal) { + if (signal == null) { + return; + } + try { + signal.cancel(); + } catch (RemoteException e) { + Slog.e(TAG, "Error requesting a cancellation", e); + } + } + + private class FillCallbackImpl extends IFillCallback.Stub { + final AndroidFuture<FillResponse> mFillRequest; + final AtomicReference<AndroidFuture<FillResponse>> mFutureRef; + final AtomicReference<ICancellationSignal> mCancellationSink; + + FillCallbackImpl(AndroidFuture<FillResponse> fillRequest, + AtomicReference<AndroidFuture<FillResponse>> futureRef, + AtomicReference<ICancellationSignal> cancellationSink) { + mFillRequest = fillRequest; + mFutureRef = futureRef; + mCancellationSink = cancellationSink; + } + + @Override + public void onCancellable(ICancellationSignal cancellation) { + AndroidFuture<FillResponse> future = mFutureRef.get(); + if (future != null && future.isCancelled()) { + dispatchCancellationSignal(cancellation); + } else { + mCancellationSink.set(cancellation); + } + } + + @Override + public void onSuccess(FillResponse response) { + mFillRequest.complete(response); + } + + @Override + public void onFailure(int requestId, CharSequence message) { + String errorMessage = message == null ? "" : String.valueOf(message); + mFillRequest.completeExceptionally( + new RuntimeException(errorMessage)); + } + } +} diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index 7e277ba3c0d0..b0445ae6d886 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -31,6 +31,7 @@ import static android.view.autofill.AutofillManager.ACTION_START_SESSION; import static android.view.autofill.AutofillManager.ACTION_VALUE_CHANGED; import static android.view.autofill.AutofillManager.ACTION_VIEW_ENTERED; import static android.view.autofill.AutofillManager.ACTION_VIEW_EXITED; +import static android.view.autofill.AutofillManager.FLAG_ENABLED_CLIENT_SUGGESTIONS; import static android.view.autofill.AutofillManager.FLAG_SMART_SUGGESTION_SYSTEM; import static android.view.autofill.AutofillManager.getSmartSuggestionModeToString; @@ -61,6 +62,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.IntentSender; +import android.content.pm.ApplicationInfo; import android.graphics.Bitmap; import android.graphics.Rect; import android.graphics.drawable.Drawable; @@ -364,6 +366,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState */ private final AssistDataReceiverImpl mAssistReceiver = new AssistDataReceiverImpl(); + @Nullable + private ClientSuggestionsSession mClientSuggestionsSession; + // TODO(b/216576510): Share one BroadcastReceiver between all Sessions instead of creating a // new one per Session. private final BroadcastReceiver mDelayedFillBroadcastReceiver = @@ -456,6 +461,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState /** Whether the current {@link FillResponse} is expired. */ private boolean mExpiredResponse; + /** Whether the client is using {@link android.view.autofill.AutofillRequestCallback}. */ + private boolean mClientSuggestionsEnabled; + /** Whether the fill dialog UI is disabled. */ private boolean mFillDialogDisabled; } @@ -486,14 +494,21 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } mWaitForInlineRequest = inlineSuggestionsRequest != null; mPendingInlineSuggestionsRequest = inlineSuggestionsRequest; - maybeRequestFillLocked(); + mWaitForInlineRequest = inlineSuggestionsRequest != null; + maybeRequestFillFromServiceLocked(); viewState.resetState(ViewState.STATE_PENDING_CREATE_INLINE_REQUEST); } } : null; } + void newAutofillRequestLocked(@Nullable InlineSuggestionsRequest inlineRequest) { + mPendingFillRequest = null; + mWaitForInlineRequest = inlineRequest != null; + mPendingInlineSuggestionsRequest = inlineRequest; + } + @GuardedBy("mLock") - void maybeRequestFillLocked() { + void maybeRequestFillFromServiceLocked() { if (mPendingFillRequest == null) { return; } @@ -503,10 +518,14 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState return; } - mPendingFillRequest = new FillRequest(mPendingFillRequest.getId(), - mPendingFillRequest.getFillContexts(), mPendingFillRequest.getClientState(), - mPendingFillRequest.getFlags(), mPendingInlineSuggestionsRequest, - mPendingFillRequest.getDelayedFillIntentSender()); + if (mPendingInlineSuggestionsRequest.isServiceSupported()) { + mPendingFillRequest = new FillRequest(mPendingFillRequest.getId(), + mPendingFillRequest.getFillContexts(), + mPendingFillRequest.getClientState(), + mPendingFillRequest.getFlags(), + mPendingInlineSuggestionsRequest, + mPendingFillRequest.getDelayedFillIntentSender()); + } } mLastFillRequest = mPendingFillRequest; @@ -618,7 +637,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState : mDelayedFillPendingIntent.getIntentSender()); mPendingFillRequest = request; - maybeRequestFillLocked(); + maybeRequestFillFromServiceLocked(); } if (mActivityToken != null) { @@ -843,30 +862,39 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } /** - * Cancels the last request sent to the {@link #mRemoteFillService}. + * Cancels the last request sent to the {@link #mRemoteFillService} or the + * {@link #mClientSuggestionsSession}. */ @GuardedBy("mLock") private void cancelCurrentRequestLocked() { - if (mRemoteFillService == null) { - wtf(null, "cancelCurrentRequestLocked() called without a remote service. " - + "mForAugmentedAutofillOnly: %s", mSessionFlags.mAugmentedAutofillOnly); + if (mRemoteFillService == null && mClientSuggestionsSession == null) { + wtf(null, "cancelCurrentRequestLocked() called without a remote service or a " + + "client suggestions session. mForAugmentedAutofillOnly: %s", + mSessionFlags.mAugmentedAutofillOnly); return; } - final int canceledRequest = mRemoteFillService.cancelCurrentRequest(); - // Remove the FillContext as there will never be a response for the service - if (canceledRequest != INVALID_REQUEST_ID && mContexts != null) { - final int numContexts = mContexts.size(); + if (mRemoteFillService != null) { + final int canceledRequest = mRemoteFillService.cancelCurrentRequest(); - // It is most likely the last context, hence search backwards - for (int i = numContexts - 1; i >= 0; i--) { - if (mContexts.get(i).getRequestId() == canceledRequest) { - if (sDebug) Slog.d(TAG, "cancelCurrentRequest(): id = " + canceledRequest); - mContexts.remove(i); - break; + // Remove the FillContext as there will never be a response for the service + if (canceledRequest != INVALID_REQUEST_ID && mContexts != null) { + final int numContexts = mContexts.size(); + + // It is most likely the last context, hence search backwards + for (int i = numContexts - 1; i >= 0; i--) { + if (mContexts.get(i).getRequestId() == canceledRequest) { + if (sDebug) Slog.d(TAG, "cancelCurrentRequest(): id = " + canceledRequest); + mContexts.remove(i); + break; + } } } } + + if (mClientSuggestionsSession != null) { + mClientSuggestionsSession.cancelCurrentRequest(); + } } private boolean isViewFocusedLocked(int flags) { @@ -931,17 +959,30 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState // structure is taken. This causes only one fill request per burst of focus changes. cancelCurrentRequestLocked(); - // Only ask IME to create inline suggestions request if Autofill provider supports it and - // the render service is available except the autofill is triggered manually and the view - // is also not focused. + // Only ask IME to create inline suggestions request when + // 1. Autofill provider supports it or client enabled client suggestions. + // 2. The render service is available. + // 3. The view is focused. (The view may not be focused if the autofill is triggered + // manually.) final RemoteInlineSuggestionRenderService remoteRenderService = mService.getRemoteInlineSuggestionRenderServiceLocked(); - if (mSessionFlags.mInlineSupportedByService + if ((mSessionFlags.mInlineSupportedByService || mSessionFlags.mClientSuggestionsEnabled) && remoteRenderService != null - && (isViewFocusedLocked(flags) || isRequestSupportFillDialog(flags))) { - Consumer<InlineSuggestionsRequest> inlineSuggestionsRequestConsumer = - mAssistReceiver.newAutofillRequestLocked(viewState, - /* isInlineRequest= */ true); + && (isViewFocusedLocked(flags) || (isRequestSupportFillDialog(flags)))) { + final Consumer<InlineSuggestionsRequest> inlineSuggestionsRequestConsumer; + if (mSessionFlags.mClientSuggestionsEnabled) { + final int finalRequestId = requestId; + inlineSuggestionsRequestConsumer = (inlineSuggestionsRequest) -> { + // Using client suggestions + synchronized (mLock) { + onClientFillRequestLocked(finalRequestId, inlineSuggestionsRequest); + } + viewState.resetState(ViewState.STATE_PENDING_CREATE_INLINE_REQUEST); + }; + } else { + inlineSuggestionsRequestConsumer = mAssistReceiver.newAutofillRequestLocked( + viewState, /* isInlineRequest= */ true); + } if (inlineSuggestionsRequestConsumer != null) { final AutofillId focusedId = mCurrentViewId; final int requestIdCopy = requestId; @@ -957,10 +998,18 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState ); viewState.setState(ViewState.STATE_PENDING_CREATE_INLINE_REQUEST); } + } else if (mSessionFlags.mClientSuggestionsEnabled) { + // Request client suggestions for the dropdown mode + onClientFillRequestLocked(requestId, null); } else { mAssistReceiver.newAutofillRequestLocked(viewState, /* isInlineRequest= */ false); } + if (mSessionFlags.mClientSuggestionsEnabled) { + // Using client suggestions, unnecessary request AssistStructure + return; + } + // Now request the assist structure data. requestAssistStructureLocked(requestId, flags); } @@ -1020,10 +1069,13 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mComponentName = componentName; mCompatMode = compatMode; mSessionState = STATE_ACTIVE; + synchronized (mLock) { mSessionFlags = new SessionFlags(); mSessionFlags.mAugmentedAutofillOnly = forAugmentedAutofillOnly; mSessionFlags.mInlineSupportedByService = mService.isInlineSuggestionsEnabledLocked(); + mSessionFlags.mClientSuggestionsEnabled = + (mFlags & FLAG_ENABLED_CLIENT_SUGGESTIONS) != 0; setClientLocked(client); } @@ -1135,12 +1187,13 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState if (requestLog != null) { requestLog.addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_DATASETS, -1); } - processNullResponseLocked(requestId, requestFlags); + processNullResponseOrFallbackLocked(requestId, requestFlags); return; } fieldClassificationIds = response.getFieldClassificationIds(); - if (fieldClassificationIds != null && !mService.isFieldClassificationEnabledLocked()) { + if (!mSessionFlags.mClientSuggestionsEnabled && fieldClassificationIds != null + && !mService.isFieldClassificationEnabledLocked()) { Slog.w(TAG, "Ignoring " + response + " because field detection is disabled"); processNullResponseLocked(requestId, requestFlags); return; @@ -1225,6 +1278,26 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } } + @GuardedBy("mLock") + private void processNullResponseOrFallbackLocked(int requestId, int flags) { + if (!mSessionFlags.mClientSuggestionsEnabled) { + processNullResponseLocked(requestId, flags); + return; + } + + // fallback to the default platform password manager + mSessionFlags.mClientSuggestionsEnabled = false; + + final InlineSuggestionsRequest inlineRequest = + (mLastInlineSuggestionsRequest != null + && mLastInlineSuggestionsRequest.first == requestId) + ? mLastInlineSuggestionsRequest.second : null; + mAssistReceiver.newAutofillRequestLocked(inlineRequest); + requestAssistStructureLocked(requestId, + flags & ~FLAG_ENABLED_CLIENT_SUGGESTIONS); + return; + } + // FillServiceCallbacks @Override public void onFillRequestFailure(int requestId, @Nullable CharSequence message) { @@ -3196,13 +3269,22 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState filterText = value.getTextValue().toString(); } - final CharSequence serviceLabel; - final Drawable serviceIcon; + final CharSequence targetLabel; + final Drawable targetIcon; synchronized (mLock) { - serviceLabel = mService.getServiceLabelLocked(); - serviceIcon = mService.getServiceIconLocked(); + if (mSessionFlags.mClientSuggestionsEnabled) { + final ApplicationInfo appInfo = ClientSuggestionsSession.getAppInfo(mComponentName, + mService.getUserId()); + targetLabel = ClientSuggestionsSession.getAppLabelLocked( + mService.getMaster().getContext(), appInfo); + targetIcon = ClientSuggestionsSession.getAppIconLocked( + mService.getMaster().getContext(), appInfo); + } else { + targetLabel = mService.getServiceLabelLocked(); + targetIcon = mService.getServiceIconLocked(); + } } - if (serviceLabel == null || serviceIcon == null) { + if (targetLabel == null || targetIcon == null) { wtf(null, "onFillReady(): no service label or icon"); return; } @@ -3233,7 +3315,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState getUiForShowing().showFillUi(filledId, response, filterText, mService.getServicePackageName(), mComponentName, - serviceLabel, serviceIcon, this, id, mCompatMode); + targetLabel, targetIcon, this, id, mCompatMode); synchronized (mLock) { mService.logDatasetShown(id, mClientState, UI_TYPE_MENU); @@ -3362,6 +3444,17 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState return false; } + final InlineSuggestionsRequest request = inlineSuggestionsRequest.get(); + if (mSessionFlags.mClientSuggestionsEnabled && !request.isClientSupported() + || !mSessionFlags.mClientSuggestionsEnabled && !request.isServiceSupported()) { + if (sDebug) { + Slog.d(TAG, "Inline suggestions not supported for " + + (mSessionFlags.mClientSuggestionsEnabled ? "client" : "service") + + ". Falling back to dropdown."); + } + return false; + } + final RemoteInlineSuggestionRenderService remoteRenderService = mService.getRemoteInlineSuggestionRenderServiceLocked(); if (remoteRenderService == null) { @@ -3370,7 +3463,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } final InlineFillUi.InlineFillUiInfo inlineFillUiInfo = - new InlineFillUi.InlineFillUiInfo(inlineSuggestionsRequest.get(), focusedId, + new InlineFillUi.InlineFillUiInfo(request, focusedId, filterText, remoteRenderService, userId, id); InlineFillUi inlineFillUi = InlineFillUi.forAutofill(inlineFillUiInfo, response, new InlineFillUi.InlineSuggestionUiCallback() { @@ -3980,6 +4073,25 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } } + @GuardedBy("mLock") + private void onClientFillRequestLocked(int requestId, + InlineSuggestionsRequest inlineSuggestionsRequest) { + if (mClientSuggestionsSession == null) { + mClientSuggestionsSession = new ClientSuggestionsSession(id, mClient, mHandler, + mComponentName, this); + } + + if (mContexts == null) { + mContexts = new ArrayList<>(1); + } + + if (inlineSuggestionsRequest != null && !inlineSuggestionsRequest.isClientSupported()) { + inlineSuggestionsRequest = null; + } + + mClientSuggestionsSession.onFillRequest(requestId, inlineSuggestionsRequest, mFlags); + } + /** * The result of checking whether to show the save dialog, when session can be saved. * diff --git a/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java index e80a6d9e0907..9f0deea503cf 100644 --- a/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java +++ b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java @@ -235,60 +235,7 @@ public class PackageManagerBackupAgent extends BackupAgent { return; } - long homeVersion = 0; - ArrayList<byte[]> homeSigHashes = null; - PackageInfo homeInfo = null; - String homeInstaller = null; - ComponentName home = getPreferredHomeComponent(); - if (home != null) { - try { - homeInfo = mPackageManager.getPackageInfoAsUser(home.getPackageName(), - PackageManager.GET_SIGNING_CERTIFICATES, mUserId); - homeInstaller = mPackageManager.getInstallerPackageName(home.getPackageName()); - homeVersion = homeInfo.getLongVersionCode(); - SigningInfo signingInfo = homeInfo.signingInfo; - if (signingInfo == null) { - Slog.e(TAG, "Home app has no signing information"); - } else { - // retrieve the newest sigs to back up - // TODO (b/73988180) use entire signing history in case of rollbacks - Signature[] homeInfoSignatures = signingInfo.getApkContentsSigners(); - homeSigHashes = BackupUtils.hashSignatureArray(homeInfoSignatures); - } - } catch (NameNotFoundException e) { - Slog.w(TAG, "Can't access preferred home info"); - // proceed as though there were no preferred home set - home = null; - } - } - try { - // We need to push a new preferred-home-app record if: - // 1. the version of the home app has changed since our last backup; - // 2. the home app [or absence] we now use differs from the prior state, - // OR 3. it looks like we use the same home app + version as before, but - // the signatures don't match so we treat them as different apps. - PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class); - final boolean needHomeBackup = (homeVersion != mStoredHomeVersion) - || !Objects.equals(home, mStoredHomeComponent) - || (home != null - && !BackupUtils.signaturesMatch(mStoredHomeSigHashes, homeInfo, pmi)); - if (needHomeBackup) { - if (DEBUG) { - Slog.i(TAG, "Home preference changed; backing up new state " + home); - } - if (home != null) { - outputBuffer.reset(); - outputBufferStream.writeUTF(home.flattenToString()); - outputBufferStream.writeLong(homeVersion); - outputBufferStream.writeUTF(homeInstaller != null ? homeInstaller : "" ); - writeSignatureHashArray(outputBufferStream, homeSigHashes); - writeEntity(data, DEFAULT_HOME_KEY, outputBuffer.toByteArray()); - } else { - data.writeEntityHeader(DEFAULT_HOME_KEY, -1); - } - } - /* * Global metadata: * @@ -403,7 +350,7 @@ public class PackageManagerBackupAgent extends BackupAgent { } // Finally, write the new state blob -- just the list of all apps we handled - writeStateFile(mAllPackages, home, homeVersion, homeSigHashes, newState); + writeStateFile(mAllPackages, newState); } private static void writeEntity(BackupDataOutput data, String key, byte[] bytes) @@ -623,8 +570,7 @@ public class PackageManagerBackupAgent extends BackupAgent { } // Util: write out our new backup state file - private void writeStateFile(List<PackageInfo> pkgs, ComponentName preferredHome, - long homeVersion, ArrayList<byte[]> homeSigHashes, ParcelFileDescriptor stateFile) { + private void writeStateFile(List<PackageInfo> pkgs, ParcelFileDescriptor stateFile) { FileOutputStream outstream = new FileOutputStream(stateFile.getFileDescriptor()); BufferedOutputStream outbuf = new BufferedOutputStream(outstream); DataOutputStream out = new DataOutputStream(outbuf); @@ -635,14 +581,6 @@ public class PackageManagerBackupAgent extends BackupAgent { out.writeUTF(STATE_FILE_HEADER); out.writeInt(STATE_FILE_VERSION); - // If we remembered a preferred home app, record that - if (preferredHome != null) { - out.writeUTF(DEFAULT_HOME_KEY); - out.writeUTF(preferredHome.flattenToString()); - out.writeLong(homeVersion); - writeSignatureHashArray(out, homeSigHashes); - } - // Conclude with the metadata block out.writeUTF(GLOBAL_METADATA_KEY); out.writeInt(Build.VERSION.SDK_INT); @@ -789,6 +727,8 @@ public class PackageManagerBackupAgent extends BackupAgent { + Build.VERSION.INCREMENTAL + ")"); } } else if (key.equals(DEFAULT_HOME_KEY)) { + // Default home app data is no longer backed up by this agent. This code is + // kept to handle restore of old backups that still contain home app data. String cn = inputBufferStream.readUTF(); mRestoredHome = ComponentName.unflattenFromString(cn); mRestoredHomeVersion = inputBufferStream.readLong(); diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java index 1af35af9fc17..e886ed084e7f 100644 --- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java +++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java @@ -85,7 +85,6 @@ import android.os.PowerSaveState; import android.os.Process; import android.os.RemoteException; import android.os.SELinux; -import android.os.ServiceManager; import android.os.SystemClock; import android.os.UserHandle; import android.os.WorkSource; @@ -3986,7 +3985,7 @@ public class UserBackupManagerService { String callerLogString = "BMS.filterAppsEligibleForBackup"; TransportConnection transportConnection = mTransportManager.getCurrentTransportClient(callerLogString); - List<String> eligibleApps = new LinkedList<>(); + List<String> eligibleApps = new ArrayList<>(); for (String packageName : packages) { if (mScheduledBackupEligibility.appIsRunningAndEligibleForBackupWithTransport( transportConnection, packageName)) { @@ -3996,7 +3995,7 @@ public class UserBackupManagerService { if (transportConnection != null) { mTransportManager.disposeOfTransportClient(transportConnection, callerLogString); } - return eligibleApps.toArray(new String[eligibleApps.size()]); + return eligibleApps.toArray(new String[0]); } finally { Binder.restoreCallingIdentity(oldToken); } @@ -4144,6 +4143,24 @@ public class UserBackupManagerService { pw.print(" : "); pw.println(entry.packageName); } + pw.println(userPrefix + "Agent timeouts:"); + pw.println(" KvBackupAgentTimeoutMillis: " + + mAgentTimeoutParameters.getKvBackupAgentTimeoutMillis()); + pw.println(" FullBackupAgentTimeoutMillis: " + + mAgentTimeoutParameters.getFullBackupAgentTimeoutMillis()); + pw.println(" SharedBackupAgentTimeoutMillis: " + + mAgentTimeoutParameters.getSharedBackupAgentTimeoutMillis()); + pw.println(" RestoreAgentTimeoutMillis (system): " + + mAgentTimeoutParameters.getRestoreAgentTimeoutMillis( + Process.FIRST_APPLICATION_UID - 1)); + pw.println(" RestoreAgentTimeoutMillis: " + + mAgentTimeoutParameters.getRestoreAgentTimeoutMillis( + Process.FIRST_APPLICATION_UID)); + pw.println(" RestoreAgentFinishedTimeoutMillis: " + + mAgentTimeoutParameters.getRestoreAgentFinishedTimeoutMillis()); + pw.println(" QuotaExceededTimeoutMillis: " + + mAgentTimeoutParameters.getQuotaExceededTimeoutMillis()); + } } diff --git a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java index 76df8b9f84e8..e78c8d1ddcac 100644 --- a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java +++ b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java @@ -24,8 +24,10 @@ import static com.android.server.backup.UserBackupManagerService.BACKUP_METADATA import static com.android.server.backup.UserBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE; import static com.android.server.backup.internal.BackupHandler.MSG_RESTORE_OPERATION_TIMEOUT; +import android.annotation.NonNull; import android.app.ApplicationThreadConstants; import android.app.IBackupAgent; +import android.app.backup.BackupAgent; import android.app.backup.BackupManager; import android.app.backup.FullBackup; import android.app.backup.IBackupManagerMonitor; @@ -38,10 +40,12 @@ import android.content.pm.Signature; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.provider.Settings; +import android.system.OsConstants; import android.text.TextUtils; import android.util.Slog; import com.android.internal.annotations.GuardedBy; +import com.android.internal.annotations.VisibleForTesting; import com.android.server.LocalServices; import com.android.server.backup.BackupAgentTimeoutParameters; import com.android.server.backup.BackupRestoreTask; @@ -57,6 +61,7 @@ import com.android.server.backup.utils.FullBackupRestoreObserverUtils; import com.android.server.backup.utils.RestoreUtils; import com.android.server.backup.utils.TarBackupReader; +import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -135,6 +140,8 @@ public class FullRestoreEngine extends RestoreEngine { private boolean mPipesClosed; private final BackupEligibilityRules mBackupEligibilityRules; + private FileMetadata mReadOnlyParent = null; + public FullRestoreEngine( UserBackupManagerService backupManagerService, OperationStorage operationStorage, BackupRestoreTask monitorTask, IFullBackupRestoreObserver observer, @@ -158,6 +165,22 @@ public class FullRestoreEngine extends RestoreEngine { mBackupEligibilityRules = backupEligibilityRules; } + @VisibleForTesting + FullRestoreEngine() { + mIsAdbRestore = false; + mAllowApks = false; + mEphemeralOpToken = 0; + mUserId = 0; + mBackupEligibilityRules = null; + mAgentTimeoutParameters = null; + mBuffer = null; + mBackupManagerService = null; + mOperationStorage = null; + mMonitor = null; + mMonitorTask = null; + mOnlyPackage = null; + } + public IBackupAgent getAgent() { return mAgent; } @@ -397,6 +420,11 @@ public class FullRestoreEngine extends RestoreEngine { okay = false; } + if (shouldSkipReadOnlyDir(info)) { + // b/194894879: We don't support restore of read-only dirs. + okay = false; + } + // At this point we have an agent ready to handle the full // restore data as well as a pipe for sending data to // that agent. Tell the agent to start reading from the @@ -573,6 +601,45 @@ public class FullRestoreEngine extends RestoreEngine { return (info != null); } + boolean shouldSkipReadOnlyDir(FileMetadata info) { + if (isValidParent(mReadOnlyParent, info)) { + // This file has a read-only parent directory, we shouldn't + // restore it. + return true; + } else { + // We're now in a different branch of the file tree, update the parent + // value. + if (isReadOnlyDir(info)) { + // Current directory is read-only. Remember it so that we can skip all + // of its contents. + mReadOnlyParent = info; + Slog.w(TAG, "Skipping restore of " + info.path + " and its contents as " + + "read-only dirs are currently not supported."); + return true; + } else { + mReadOnlyParent = null; + } + } + + return false; + } + + private static boolean isValidParent(FileMetadata parentDir, @NonNull FileMetadata childDir) { + return parentDir != null + && childDir.packageName.equals(parentDir.packageName) + && childDir.domain.equals(parentDir.domain) + && childDir.path.startsWith(getPathWithTrailingSeparator(parentDir.path)); + } + + private static String getPathWithTrailingSeparator(String path) { + return path.endsWith(File.separator) ? path : path + File.separator; + } + + private static boolean isReadOnlyDir(FileMetadata file) { + // Check if owner has 'write' bit in the file's mode value (see 'man -7 inode' for details). + return file.type == BackupAgent.TYPE_DIRECTORY && (file.mode & OsConstants.S_IWUSR) == 0; + } + private void setUpPipes() throws IOException { synchronized (mPipesLock) { mPipes = ParcelFileDescriptor.createPipe(); diff --git a/services/companion/java/com/android/server/companion/AssociationRequestsProcessor.java b/services/companion/java/com/android/server/companion/AssociationRequestsProcessor.java index 7a5fa628f645..47d2640ffc3d 100644 --- a/services/companion/java/com/android/server/companion/AssociationRequestsProcessor.java +++ b/services/companion/java/com/android/server/companion/AssociationRequestsProcessor.java @@ -26,6 +26,7 @@ import static com.android.server.companion.CompanionDeviceManagerService.DEBUG; import static com.android.server.companion.PackageUtils.enforceUsesCompanionDeviceFeature; import static com.android.server.companion.PermissionsUtils.enforcePermissionsForAssociation; import static com.android.server.companion.RolesUtils.isRoleHolder; +import static com.android.server.companion.Utils.prepareForIpc; import static java.util.Objects.requireNonNull; @@ -47,7 +48,6 @@ import android.net.MacAddress; import android.os.Binder; import android.os.Bundle; import android.os.Handler; -import android.os.Parcel; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.UserHandle; @@ -413,20 +413,4 @@ class AssociationRequestsProcessor { return requestingPackageSignatureAllowlisted; } - - /** - * Convert an instance of a "locally-defined" ResultReceiver to an instance of - * {@link android.os.ResultReceiver} itself, which the receiving process will be able to - * unmarshall. - */ - private static <T extends ResultReceiver> ResultReceiver prepareForIpc(T resultReceiver) { - final Parcel parcel = Parcel.obtain(); - resultReceiver.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - - final ResultReceiver ipcFriendly = ResultReceiver.CREATOR.createFromParcel(parcel); - parcel.recycle(); - - return ipcFriendly; - } } diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java index b4c107c1a2c1..092444ad35ed 100644 --- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java @@ -99,6 +99,8 @@ import com.android.internal.util.DumpUtils; import com.android.server.FgThread; import com.android.server.LocalServices; import com.android.server.SystemService; +import com.android.server.companion.datatransfer.SystemDataTransferProcessor; +import com.android.server.companion.datatransfer.SystemDataTransferRequestStore; import com.android.server.companion.presence.CompanionDevicePresenceMonitor; import com.android.server.pm.UserManagerInternal; @@ -130,7 +132,9 @@ public class CompanionDeviceManagerService extends SystemService { private final PersistUserStateHandler mUserPersistenceHandler; private final AssociationStoreImpl mAssociationStore; + private final SystemDataTransferRequestStore mSystemDataTransferRequestStore; private AssociationRequestsProcessor mAssociationRequestsProcessor; + private SystemDataTransferProcessor mSystemDataTransferProcessor; private CompanionDevicePresenceMonitor mDevicePresenceMonitor; private CompanionApplicationController mCompanionAppController; @@ -164,6 +168,7 @@ public class CompanionDeviceManagerService extends SystemService { mUserPersistenceHandler = new PersistUserStateHandler(); mAssociationStore = new AssociationStoreImpl(); + mSystemDataTransferRequestStore = new SystemDataTransferRequestStore(); } @Override @@ -178,6 +183,8 @@ public class CompanionDeviceManagerService extends SystemService { mAssociationRequestsProcessor = new AssociationRequestsProcessor( /* cdmService */this, mAssociationStore); + mSystemDataTransferProcessor = new SystemDataTransferProcessor(this, mAssociationStore, + mSystemDataTransferRequestStore); final Context context = getContext(); mCompanionAppController = new CompanionApplicationController( @@ -602,6 +609,18 @@ public class CompanionDeviceManagerService extends SystemService { } @Override + public PendingIntent buildPermissionTransferUserConsentIntent(String packageName, + int userId, int associationId) throws RemoteException { + return mSystemDataTransferProcessor.buildPermissionTransferUserConsentIntent( + packageName, userId, associationId); + } + + @Override + public void startSystemDataTransfer(int userId, int associationId) throws RemoteException { + // TODO(b/222121838) + } + + @Override public void notifyDeviceAppeared(int associationId) { if (DEBUG) Log.i(TAG, "notifyDevice_Appeared() id=" + associationId); @@ -863,6 +882,9 @@ public class CompanionDeviceManagerService extends SystemService { mAssociationStore.removeAssociation(associationId); logRemoveAssociation(deviceProfile); + // Remove all the system data transfer requests for the association. + mSystemDataTransferRequestStore.removeRequestsByAssociationId(userId, associationId); + final List<AssociationInfo> otherAssociations = mAssociationStore.getAssociationsForPackage(userId, packageName); diff --git a/services/companion/java/com/android/server/companion/DataStoreUtils.java b/services/companion/java/com/android/server/companion/DataStoreUtils.java index 8ac741a44ee5..73e68ec0bf97 100644 --- a/services/companion/java/com/android/server/companion/DataStoreUtils.java +++ b/services/companion/java/com/android/server/companion/DataStoreUtils.java @@ -33,15 +33,24 @@ import org.xmlpull.v1.XmlPullParserException; import java.io.File; import java.io.FileOutputStream; -final class DataStoreUtils { +/** + * Util class for CDM data stores + */ +public final class DataStoreUtils { private static final String TAG = "CompanionDevice_DataStoreUtils"; - static boolean isStartOfTag(@NonNull XmlPullParser parser, @NonNull String tag) + /** + * Check if the parser pointer is at the start of the tag + */ + public static boolean isStartOfTag(@NonNull XmlPullParser parser, @NonNull String tag) throws XmlPullParserException { return parser.getEventType() == START_TAG && tag.equals(parser.getName()); } - static boolean isEndOfTag(@NonNull XmlPullParser parser, @NonNull String tag) + /** + * Check if the parser pointer is at the end of the tag + */ + public static boolean isEndOfTag(@NonNull XmlPullParser parser, @NonNull String tag) throws XmlPullParserException { return parser.getEventType() == END_TAG && tag.equals(parser.getName()); } @@ -57,7 +66,7 @@ final class DataStoreUtils { * @return an AtomicFile for the user */ @NonNull - static AtomicFile createStorageFileForUser(@UserIdInt int userId, String fileName) { + public static AtomicFile createStorageFileForUser(@UserIdInt int userId, String fileName) { return new AtomicFile(getBaseStorageFileForUser(userId, fileName)); } @@ -70,7 +79,7 @@ final class DataStoreUtils { * Writing to file could fail, for example, if the user has been recently removed and so was * their DE (/data/system_de/<user-id>/) directory. */ - static void writeToFileSafely( + public static void writeToFileSafely( @NonNull AtomicFile file, @NonNull ThrowingConsumer<FileOutputStream> consumer) { try { file.write(consumer); diff --git a/services/companion/java/com/android/server/companion/PackageUtils.java b/services/companion/java/com/android/server/companion/PackageUtils.java index a2b20593a9cb..42c7687f0f28 100644 --- a/services/companion/java/com/android/server/companion/PackageUtils.java +++ b/services/companion/java/com/android/server/companion/PackageUtils.java @@ -41,8 +41,8 @@ import android.util.Slog; import com.android.internal.util.ArrayUtils; +import java.util.ArrayList; import java.util.HashMap; -import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -87,7 +87,8 @@ final class PackageUtils { final List<ResolveInfo> companionServices = pm.queryIntentServicesAsUser( COMPANION_SERVICE_INTENT, ResolveInfoFlags.of(0), userId); - final Map<String, List<ComponentName>> packageNameToServiceInfoList = new HashMap<>(); + final Map<String, List<ComponentName>> packageNameToServiceInfoList = + new HashMap<>(companionServices.size()); for (ResolveInfo resolveInfo : companionServices) { final ServiceInfo service = resolveInfo.serviceInfo; @@ -101,19 +102,19 @@ final class PackageUtils { continue; } - // Use LinkedList, because we'll need to prepend "primary" services, while appending the - // other (non-primary) services to the list. - final LinkedList<ComponentName> services = - (LinkedList<ComponentName>) packageNameToServiceInfoList.computeIfAbsent( - service.packageName, it -> new LinkedList<>()); + // We'll need to prepend "primary" services, while appending the other (non-primary) + // services to the list. + final ArrayList<ComponentName> services = + (ArrayList<ComponentName>) packageNameToServiceInfoList.computeIfAbsent( + service.packageName, it -> new ArrayList<>(1)); final ComponentName componentName = service.getComponentName(); if (isPrimaryCompanionDeviceService(pm, componentName)) { // "Primary" service should be at the head of the list. - services.addFirst(componentName); + services.add(0, componentName); } else { - services.addLast(componentName); + services.add(componentName); } } diff --git a/services/companion/java/com/android/server/companion/PersistentDataStore.java b/services/companion/java/com/android/server/companion/PersistentDataStore.java index 36393894f727..4d42838fff50 100644 --- a/services/companion/java/com/android/server/companion/PersistentDataStore.java +++ b/services/companion/java/com/android/server/companion/PersistentDataStore.java @@ -103,7 +103,7 @@ import java.util.concurrent.ConcurrentMap; * Since Android T the data is stored to "companion_device_manager.xml" file in * {@link Environment#getDataSystemDeDirectory(int) /data/system_de/}. * - * See {@link #getBaseStorageFileForUser(int) getBaseStorageFileForUser()} + * See {@link #getStorageFileForUser(int)} * * <p> * Since Android T the data is stored using the v1 schema. diff --git a/services/companion/java/com/android/server/companion/Utils.java b/services/companion/java/com/android/server/companion/Utils.java new file mode 100644 index 000000000000..b9f61ecd8c4f --- /dev/null +++ b/services/companion/java/com/android/server/companion/Utils.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.companion; + +import android.os.Parcel; +import android.os.ResultReceiver; + +/** + * A miscellaneous util class for CDM + * + * @hide + */ +public final class Utils { + + /** + * Convert an instance of a "locally-defined" ResultReceiver to an instance of + * {@link android.os.ResultReceiver} itself, which the receiving process will be able to + * unmarshall. + * @hide + */ + public static <T extends ResultReceiver> ResultReceiver prepareForIpc(T resultReceiver) { + final Parcel parcel = Parcel.obtain(); + resultReceiver.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + + final ResultReceiver ipcFriendly = ResultReceiver.CREATOR.createFromParcel(parcel); + parcel.recycle(); + + return ipcFriendly; + } + + private Utils() {} +} diff --git a/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferProcessor.java b/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferProcessor.java new file mode 100644 index 000000000000..ca47453b26a4 --- /dev/null +++ b/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferProcessor.java @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.companion.datatransfer; + +import static android.app.PendingIntent.FLAG_CANCEL_CURRENT; +import static android.app.PendingIntent.FLAG_IMMUTABLE; +import static android.app.PendingIntent.FLAG_ONE_SHOT; +import static android.companion.CompanionDeviceManager.COMPANION_DEVICE_DISCOVERY_PACKAGE_NAME; +import static android.content.ComponentName.createRelative; + +import static com.android.server.companion.Utils.prepareForIpc; + +import android.annotation.UserIdInt; +import android.app.PendingIntent; +import android.companion.AssociationInfo; +import android.companion.DeviceNotAssociatedException; +import android.companion.datatransfer.PermissionSyncRequest; +import android.companion.datatransfer.SystemDataTransferRequest; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.os.Binder; +import android.os.Bundle; +import android.os.Handler; +import android.os.RemoteException; +import android.os.ResultReceiver; +import android.util.Slog; + +import com.android.server.companion.AssociationStore; +import com.android.server.companion.CompanionDeviceManagerService; + +import java.util.List; + +/** + * This processor builds user consent intent for a given SystemDataTransferRequest and processes the + * request when the system is ready (a secure channel is established between the handhold and the + * companion device). + */ +public class SystemDataTransferProcessor { + + private static final String LOG_TAG = SystemDataTransferProcessor.class.getSimpleName(); + + // Values from UI to SystemDataTransferProcessor via ResultReceiver + private static final int RESULT_CODE_SYSTEM_DATA_TRANSFER_ALLOWED = 0; + private static final int RESULT_CODE_SYSTEM_DATA_TRANSFER_DISALLOWED = 1; + private static final String EXTRA_PERMISSION_SYNC_REQUEST = "permission_sync_request"; + private static final String EXTRA_COMPANION_DEVICE_NAME = "companion_device_name"; + private static final String EXTRA_SYSTEM_DATA_TRANSFER_RESULT_RECEIVER = + "system_data_transfer_result_receiver"; + private static final ComponentName SYSTEM_DATA_TRANSFER_REQUEST_APPROVAL_ACTIVITY = + createRelative(COMPANION_DEVICE_DISCOVERY_PACKAGE_NAME, + ".CompanionDeviceDataTransferActivity"); + + private final Context mContext; + private final AssociationStore mAssociationStore; + private final SystemDataTransferRequestStore mSystemDataTransferRequestStore; + + public SystemDataTransferProcessor(CompanionDeviceManagerService service, + AssociationStore associationStore, + SystemDataTransferRequestStore systemDataTransferRequestStore) { + mContext = service.getContext(); + mAssociationStore = associationStore; + mSystemDataTransferRequestStore = systemDataTransferRequestStore; + } + + /** + * Build a PendingIntent of permission sync user consent dialog + */ + public PendingIntent buildPermissionTransferUserConsentIntent(String packageName, + @UserIdInt int userId, int associationId) throws RemoteException { + // The association must exist and either belong to the calling package, + // or the calling package must hold REQUEST_SYSTEM_DATA_TRANSFER permission. + AssociationInfo association = mAssociationStore.getAssociationById(associationId); + if (association == null) { + throw new RemoteException(new DeviceNotAssociatedException( + "Association id: " + associationId + " doesn't exist.")); + } else { + if (!association.getPackageName().equals(packageName)) { + Slog.e(LOG_TAG, "The calling package doesn't own the association."); + return null; + } + + // Check if the request's data type has been requested before. + List<SystemDataTransferRequest> storedRequests = + mSystemDataTransferRequestStore.readRequestsByAssociationId(userId, + associationId); + for (SystemDataTransferRequest storedRequest : storedRequests) { + if (storedRequest instanceof PermissionSyncRequest) { + Slog.e(LOG_TAG, "The request has been sent before, you can not send " + + "the same request type again."); + return null; + } + } + } + + Slog.i(LOG_TAG, "Creating permission sync intent for userId=" + userId + + "associationId: " + associationId); + + // Create an internal intent to launch the user consent dialog + final Bundle extras = new Bundle(); + PermissionSyncRequest request = new PermissionSyncRequest(associationId); + request.setUserId(userId); + extras.putParcelable(EXTRA_PERMISSION_SYNC_REQUEST, request); + extras.putCharSequence(EXTRA_COMPANION_DEVICE_NAME, association.getDisplayName()); + extras.putParcelable(EXTRA_SYSTEM_DATA_TRANSFER_RESULT_RECEIVER, + prepareForIpc(mOnSystemDataTransferRequestConfirmationReceiver)); + + final Intent intent = new Intent(); + intent.setComponent(SYSTEM_DATA_TRANSFER_REQUEST_APPROVAL_ACTIVITY); + intent.putExtras(extras); + + // Create a PendingIntent + final long token = Binder.clearCallingIdentity(); + try { + return PendingIntent.getActivity(mContext, /*requestCode */ associationId, intent, + FLAG_ONE_SHOT | FLAG_CANCEL_CURRENT | FLAG_IMMUTABLE); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + private final ResultReceiver mOnSystemDataTransferRequestConfirmationReceiver = + new ResultReceiver(Handler.getMain()) { + @Override + protected void onReceiveResult(int resultCode, Bundle data) { + Slog.d(LOG_TAG, "onReceiveResult() code=" + resultCode + ", " + + "data=" + data); + + if (resultCode == RESULT_CODE_SYSTEM_DATA_TRANSFER_ALLOWED + || resultCode == RESULT_CODE_SYSTEM_DATA_TRANSFER_DISALLOWED) { + final PermissionSyncRequest request = + data.getParcelable(EXTRA_PERMISSION_SYNC_REQUEST, + PermissionSyncRequest.class); + if (request != null) { + request.setUserConsented( + resultCode == RESULT_CODE_SYSTEM_DATA_TRANSFER_ALLOWED); + Slog.i(LOG_TAG, "Recording request: " + request); + mSystemDataTransferRequestStore.writeRequest(request.getUserId(), + request); + } + + return; + } + + Slog.e(LOG_TAG, "Unknown result code:" + resultCode); + } + }; +} diff --git a/services/companion/java/com/android/server/companion/SystemDataTransferRequestDataStore.java b/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferRequestStore.java index 38e5d16842b9..ab0a06260cfc 100644 --- a/services/companion/java/com/android/server/companion/SystemDataTransferRequestDataStore.java +++ b/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferRequestStore.java @@ -14,14 +14,14 @@ * limitations under the License. */ -package com.android.server.companion; +package com.android.server.companion.datatransfer; + +import static android.companion.datatransfer.SystemDataTransferRequest.DATA_TYPE_PERMISSION_SYNC; import static com.android.internal.util.XmlUtils.readBooleanAttribute; import static com.android.internal.util.XmlUtils.readIntAttribute; -import static com.android.internal.util.XmlUtils.readThisListXml; import static com.android.internal.util.XmlUtils.writeBooleanAttribute; import static com.android.internal.util.XmlUtils.writeIntAttribute; -import static com.android.internal.util.XmlUtils.writeListXml; import static com.android.server.companion.DataStoreUtils.createStorageFileForUser; import static com.android.server.companion.DataStoreUtils.isEndOfTag; import static com.android.server.companion.DataStoreUtils.isStartOfTag; @@ -30,13 +30,16 @@ import static com.android.server.companion.DataStoreUtils.writeToFileSafely; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; -import android.companion.SystemDataTransferRequest; +import android.companion.datatransfer.PermissionSyncRequest; +import android.companion.datatransfer.SystemDataTransferRequest; import android.util.AtomicFile; import android.util.Slog; +import android.util.SparseArray; import android.util.TypedXmlPullParser; import android.util.TypedXmlSerializer; import android.util.Xml; +import com.android.internal.annotations.GuardedBy; import com.android.internal.util.XmlUtils; import org.xmlpull.v1.XmlPullParserException; @@ -45,46 +48,130 @@ import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; /** * The class is responsible for reading/writing SystemDataTransferRequest records from/to the disk. - * + * <p> * The following snippet is a sample XML file stored in the disk. * <pre>{@code * <requests> * <request * association_id="1" - * is_permission_sync_all_packages="false"> - * <list name="permission_sync_packages"> - * <string>com.sample.app1</string> - * <string>com.sample.app2</string> - * </list> + * data_type="1" + * user_id="12" + * is_user_consented="true" * </request> * </requests> * }</pre> */ -public class SystemDataTransferRequestDataStore { +public class SystemDataTransferRequestStore { - private static final String LOG_TAG = SystemDataTransferRequestDataStore.class.getSimpleName(); + private static final String LOG_TAG = SystemDataTransferRequestStore.class.getSimpleName(); private static final String FILE_NAME = "companion_device_system_data_transfer_requests.xml"; private static final String XML_TAG_REQUESTS = "requests"; private static final String XML_TAG_REQUEST = "request"; - private static final String XML_TAG_LIST = "list"; private static final String XML_ATTR_ASSOCIATION_ID = "association_id"; - private static final String XML_ATTR_IS_PERMISSION_SYNC_ALL_PACKAGES = - "is_permission_sync_all_packages"; - private static final String XML_ATTR_PERMISSION_SYNC_PACKAGES = "permission_sync_packages"; + private static final String XML_ATTR_DATA_TYPE = "data_type"; + private static final String XML_ATTR_USER_ID = "user_id"; + private static final String XML_ATTR_IS_USER_CONSENTED = "is_user_consented"; + + private static final int READ_FROM_DISK_TIMEOUT = 5; // in seconds + private final ExecutorService mExecutor; private final ConcurrentMap<Integer, AtomicFile> mUserIdToStorageFile = new ConcurrentHashMap<>(); + private final Object mLock = new Object(); + + @GuardedBy("mLock") + private final SparseArray<ArrayList<SystemDataTransferRequest>> mCachedPerUser = + new SparseArray<>(); + + public SystemDataTransferRequestStore() { + mExecutor = Executors.newSingleThreadExecutor(); + } + + @NonNull + List<SystemDataTransferRequest> readRequestsByAssociationId(@UserIdInt int userId, + int associationId) { + List<SystemDataTransferRequest> cachedRequests; + synchronized (mLock) { + cachedRequests = readRequestsFromCache(userId); + } + + List<SystemDataTransferRequest> requestsByAssociationId = new ArrayList<>(); + for (SystemDataTransferRequest request : cachedRequests) { + if (request.getAssociationId() == associationId) { + requestsByAssociationId.add(request); + } + } + return requestsByAssociationId; + } + + void writeRequest(@UserIdInt int userId, SystemDataTransferRequest request) { + Slog.i(LOG_TAG, "Writing request=" + request + " to store."); + ArrayList<SystemDataTransferRequest> cachedRequests; + synchronized (mLock) { + // Write to cache + cachedRequests = readRequestsFromCache(userId); + cachedRequests.add(request); + mCachedPerUser.set(userId, cachedRequests); + } + // Write to store + mExecutor.execute(() -> writeRequestsToStore(userId, cachedRequests)); + } + + /** + * Remove requests by association id. userId must be the one which owns the associationId. + */ + public void removeRequestsByAssociationId(@UserIdInt int userId, int associationId) { + Slog.i(LOG_TAG, "Removing system data transfer requests for userId=" + userId + + ", associationId=" + associationId); + ArrayList<SystemDataTransferRequest> cachedRequests; + synchronized (mLock) { + // Remove requests from cache + cachedRequests = readRequestsFromCache(userId); + cachedRequests.removeIf(request -> request.getAssociationId() == associationId); + mCachedPerUser.set(userId, cachedRequests); + } + // Remove requests from store + mExecutor.execute(() -> writeRequestsToStore(userId, cachedRequests)); + } + + @GuardedBy("mLock") + private ArrayList<SystemDataTransferRequest> readRequestsFromCache(@UserIdInt int userId) { + ArrayList<SystemDataTransferRequest> cachedRequests = mCachedPerUser.get(userId); + if (cachedRequests == null) { + Future<ArrayList<SystemDataTransferRequest>> future = + mExecutor.submit(() -> readRequestsFromStore(userId)); + try { + cachedRequests = future.get(READ_FROM_DISK_TIMEOUT, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Slog.e(LOG_TAG, "Thread reading SystemDataTransferRequest from disk is " + + "interrupted."); + } catch (ExecutionException e) { + Slog.e(LOG_TAG, "Error occurred while reading SystemDataTransferRequest " + + "from disk."); + } catch (TimeoutException e) { + Slog.e(LOG_TAG, "Reading SystemDataTransferRequest from disk timed out."); + } + mCachedPerUser.set(userId, cachedRequests); + } + return cachedRequests; + } + /** * Reads previously persisted data for the given user * @@ -92,7 +179,7 @@ public class SystemDataTransferRequestDataStore { * @return a list of SystemDataTransferRequest */ @NonNull - List<SystemDataTransferRequest> readRequestsForUser(@UserIdInt int userId) { + private ArrayList<SystemDataTransferRequest> readRequestsFromStore(@UserIdInt int userId) { final AtomicFile file = getStorageFileForUser(userId); Slog.i(LOG_TAG, "Reading SystemDataTransferRequests for user " + userId + " from " + "file=" + file.getBaseFile().getPath()); @@ -102,59 +189,62 @@ public class SystemDataTransferRequestDataStore { synchronized (file) { if (!file.getBaseFile().exists()) { Slog.d(LOG_TAG, "File does not exist -> Abort"); - return Collections.emptyList(); + return new ArrayList<>(); } try (FileInputStream in = file.openRead()) { final TypedXmlPullParser parser = Xml.resolvePullParser(in); XmlUtils.beginDocument(parser, XML_TAG_REQUESTS); - return readRequests(parser); + return readRequestsFromXml(parser); } catch (XmlPullParserException | IOException e) { Slog.e(LOG_TAG, "Error while reading requests file", e); - return Collections.emptyList(); + return new ArrayList<>(); } } } @NonNull - private List<SystemDataTransferRequest> readRequests(@NonNull TypedXmlPullParser parser) - throws XmlPullParserException, IOException { + private ArrayList<SystemDataTransferRequest> readRequestsFromXml( + @NonNull TypedXmlPullParser parser) throws XmlPullParserException, IOException { if (!isStartOfTag(parser, XML_TAG_REQUESTS)) { throw new XmlPullParserException("The XML doesn't have start tag: " + XML_TAG_REQUESTS); } - List<SystemDataTransferRequest> requests = new ArrayList<>(); + ArrayList<SystemDataTransferRequest> requests = new ArrayList<>(); while (true) { parser.nextTag(); - if (isEndOfTag(parser, XML_TAG_REQUESTS)) break; + if (isEndOfTag(parser, XML_TAG_REQUESTS)) { + break; + } if (isStartOfTag(parser, XML_TAG_REQUEST)) { - requests.add(readRequest(parser)); + requests.add(readRequestFromXml(parser)); } } return requests; } - private SystemDataTransferRequest readRequest(@NonNull TypedXmlPullParser parser) + private SystemDataTransferRequest readRequestFromXml(@NonNull TypedXmlPullParser parser) throws XmlPullParserException, IOException { if (!isStartOfTag(parser, XML_TAG_REQUEST)) { throw new XmlPullParserException("XML doesn't have start tag: " + XML_TAG_REQUEST); } final int associationId = readIntAttribute(parser, XML_ATTR_ASSOCIATION_ID); - final boolean isPermissionSyncAllPackages = readBooleanAttribute(parser, - XML_ATTR_IS_PERMISSION_SYNC_ALL_PACKAGES); - parser.nextTag(); - List<String> permissionSyncPackages = new ArrayList<>(); - if (isStartOfTag(parser, XML_TAG_LIST)) { - parser.nextTag(); - permissionSyncPackages = readThisListXml(parser, XML_TAG_LIST, - new String[1]); - } + final int dataType = readIntAttribute(parser, XML_ATTR_DATA_TYPE); + final int userId = readIntAttribute(parser, XML_ATTR_USER_ID); + final boolean isUserConsented = readBooleanAttribute(parser, XML_ATTR_IS_USER_CONSENTED); - return new SystemDataTransferRequest(associationId, isPermissionSyncAllPackages, - permissionSyncPackages); + switch (dataType) { + case DATA_TYPE_PERMISSION_SYNC: + PermissionSyncRequest request = new PermissionSyncRequest(associationId); + request.setUserId(userId); + request.setUserConsented(isUserConsented); + return request; + default: + return null; + } } /** @@ -163,7 +253,7 @@ public class SystemDataTransferRequestDataStore { * @param userId Android UserID * @param requests a list of user's SystemDataTransferRequest. */ - void writeRequestsForUser(@UserIdInt int userId, + void writeRequestsToStore(@UserIdInt int userId, @NonNull List<SystemDataTransferRequest> requests) { final AtomicFile file = getStorageFileForUser(userId); Slog.i(LOG_TAG, "Writing SystemDataTransferRequests for user " + userId + " to file=" @@ -177,37 +267,31 @@ public class SystemDataTransferRequestDataStore { serializer.setFeature( "http://xmlpull.org/v1/doc/features.html#indent-output", true); serializer.startDocument(null, true); - writeRequests(serializer, requests); + writeRequestsToXml(serializer, requests); serializer.endDocument(); }); } } - private void writeRequests(@NonNull TypedXmlSerializer serializer, + private void writeRequestsToXml(@NonNull TypedXmlSerializer serializer, @Nullable Collection<SystemDataTransferRequest> requests) throws IOException { serializer.startTag(null, XML_TAG_REQUESTS); for (SystemDataTransferRequest request : requests) { - writeRequest(serializer, request); + writeRequestToXml(serializer, request); } serializer.endTag(null, XML_TAG_REQUESTS); } - private void writeRequest(@NonNull TypedXmlSerializer serializer, + private void writeRequestToXml(@NonNull TypedXmlSerializer serializer, @NonNull SystemDataTransferRequest request) throws IOException { serializer.startTag(null, XML_TAG_REQUEST); writeIntAttribute(serializer, XML_ATTR_ASSOCIATION_ID, request.getAssociationId()); - writeBooleanAttribute(serializer, XML_ATTR_IS_PERMISSION_SYNC_ALL_PACKAGES, - request.isPermissionSyncAllPackages()); - try { - writeListXml(request.getPermissionSyncPackages(), XML_ATTR_PERMISSION_SYNC_PACKAGES, - serializer); - } catch (XmlPullParserException e) { - Slog.e(LOG_TAG, "Error writing permission sync packages into XML. " - + request.getPermissionSyncPackages().toString()); - } + writeIntAttribute(serializer, XML_ATTR_DATA_TYPE, request.getDataType()); + writeIntAttribute(serializer, XML_ATTR_USER_ID, request.getUserId()); + writeBooleanAttribute(serializer, XML_ATTR_IS_USER_CONSENTED, request.isUserConsented()); serializer.endTag(null, XML_TAG_REQUEST); } @@ -215,11 +299,12 @@ public class SystemDataTransferRequestDataStore { /** * Creates and caches {@link AtomicFile} object that represents the back-up file for the given * user. - * + * <p> * IMPORTANT: the method will ALWAYS return the same {@link AtomicFile} object, which makes it * possible to synchronize reads and writes to the file using the returned object. */ - private @NonNull AtomicFile getStorageFileForUser(@UserIdInt int userId) { + @NonNull + private AtomicFile getStorageFileForUser(@UserIdInt int userId) { return mUserIdToStorageFile.computeIfAbsent(userId, u -> createStorageFileForUser(userId, FILE_NAME)); } diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java index 06f698efde2b..58c22a75cd5b 100644 --- a/services/core/java/android/content/pm/PackageManagerInternal.java +++ b/services/core/java/android/content/pm/PackageManagerInternal.java @@ -552,18 +552,23 @@ public abstract class PackageManagerInternal { /** * Set which overlay to use for a package. * @param userId The user for which to update the overlays. - * @param targetPackageName The package name of the package for which to update the overlays. - * @param overlayPaths The complete list of overlay paths that should be enabled for + * @param pendingChanges is a map to describe all overlay targets and their related overlay + * paths. Its key is the overlay target package and its value is the + * complete list of overlay paths that should be enabled for * the target. Previously enabled overlays not specified in the list * will be disabled. Pass in null or empty paths to disable all overlays. * The order of the items is significant if several overlays modify the - * same resource. + * same resource. To pass the concrete ArrayMap type is to reduce the + * overheads of system server. * @param outUpdatedPackageNames An output list that contains the package names of packages * affected by the update of enabled overlays. - * @return true if all packages names were known by the package manager, false otherwise + * @param outInvalidPackageNames An output list that contains the package names of packages + * are not valid. */ - public abstract boolean setEnabledOverlayPackages(int userId, String targetPackageName, - @Nullable OverlayPaths overlayPaths, Set<String> outUpdatedPackageNames); + public abstract void setEnabledOverlayPackages(int userId, + @NonNull ArrayMap<String, OverlayPaths> pendingChanges, + @NonNull Set<String> outUpdatedPackageNames, + @NonNull Set<String> outInvalidPackageNames); /** * Resolves an activity intent, allowing instant apps to be resolved. diff --git a/services/core/java/com/android/server/ConsumerIrService.java b/services/core/java/com/android/server/ConsumerIrService.java index c4e84a4cd138..a9bdf063e8a6 100644 --- a/services/core/java/com/android/server/ConsumerIrService.java +++ b/services/core/java/com/android/server/ConsumerIrService.java @@ -16,6 +16,10 @@ package com.android.server; +import static android.Manifest.permission.TRANSMIT_IR; + +import android.annotation.EnforcePermission; +import android.annotation.RequiresNoPermission; import android.content.Context; import android.content.pm.PackageManager; import android.hardware.IConsumerIrService; @@ -60,6 +64,7 @@ public class ConsumerIrService extends IConsumerIrService.Stub { } @Override + @RequiresNoPermission public boolean hasIrEmitter() { return mHasNativeHal; } @@ -85,12 +90,8 @@ public class ConsumerIrService extends IConsumerIrService.Stub { @Override + @EnforcePermission(TRANSMIT_IR) public void transmit(String packageName, int carrierFrequency, int[] pattern) { - if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.TRANSMIT_IR) - != PackageManager.PERMISSION_GRANTED) { - throw new SecurityException("Requires TRANSMIT_IR permission"); - } - long totalXmitTime = 0; for (int slice : pattern) { @@ -125,12 +126,8 @@ public class ConsumerIrService extends IConsumerIrService.Stub { } @Override + @EnforcePermission(TRANSMIT_IR) public int[] getCarrierFrequencies() { - if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.TRANSMIT_IR) - != PackageManager.PERMISSION_GRANTED) { - throw new SecurityException("Requires TRANSMIT_IR permission"); - } - throwIfNoIrEmitter(); synchronized(mHalLock) { diff --git a/services/core/java/com/android/server/SystemServiceManager.java b/services/core/java/com/android/server/SystemServiceManager.java index 78df983c83f7..a562afbe442f 100644 --- a/services/core/java/com/android/server/SystemServiceManager.java +++ b/services/core/java/com/android/server/SystemServiceManager.java @@ -23,6 +23,7 @@ import android.app.ActivityManager; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.os.Environment; import android.os.SystemClock; @@ -162,16 +163,17 @@ public final class SystemServiceManager implements Dumpable { /** * Returns true if the jar is in a test APEX. */ - private static boolean isJarInTestApex(String pathStr) { + private boolean isJarInTestApex(String pathStr) { Path path = Paths.get(pathStr); if (path.getNameCount() >= 2 && path.getName(0).toString().equals("apex")) { String apexModuleName = path.getName(1).toString(); ApexManager apexManager = ApexManager.getInstance(); String packageName = apexManager.getActivePackageNameForApexModuleName(apexModuleName); - PackageInfo packageInfo = apexManager.getPackageInfo( - packageName, ApexManager.MATCH_ACTIVE_PACKAGE); - if (packageInfo != null) { + try { + PackageInfo packageInfo = mContext.getPackageManager().getPackageInfo(packageName, + PackageManager.PackageInfoFlags.of(PackageManager.MATCH_APEX)); return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_TEST_ONLY) != 0; + } catch (Exception ignore) { } } return false; diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java index 8b48d0f39aaa..a900f6fe4921 100644 --- a/services/core/java/com/android/server/Watchdog.java +++ b/services/core/java/com/android/server/Watchdog.java @@ -390,11 +390,16 @@ public class Watchdog { // potentially hold longer running operations with no guarantees about the timeliness // of operations there. // - // The shared foreground thread is the main checker. It is where we - // will also dispatch monitor checks and do other work. - mMonitorChecker = new HandlerChecker(FgThread.getHandler(), - "foreground thread"); + // Use a custom thread to check monitors to avoid lock contention from impacted other + // threads. + ServiceThread t = new ServiceThread("watchdog.monitor", + android.os.Process.THREAD_PRIORITY_DEFAULT, true /*allowIo*/); + t.start(); + mMonitorChecker = new HandlerChecker(new Handler(t.getLooper()), "monitor thread"); mHandlerCheckers.add(withDefaultTimeout(mMonitorChecker)); + + mHandlerCheckers.add(withDefaultTimeout( + new HandlerChecker(FgThread.getHandler(), "foreground thread"))); // Add checker for main thread. We only do a quick check since there // can be UI running on the thread. mHandlerCheckers.add(withDefaultTimeout( diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index b059cc7e2aa2..2c465f44aa99 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -1820,6 +1820,14 @@ public class AccountManagerService if (account == null) { return false; } + if (account.name != null && account.name.length() > 200) { + Log.w(TAG, "Account cannot be added - Name longer than 200 chars"); + return false; + } + if (account.type != null && account.type.length() > 200) { + Log.w(TAG, "Account cannot be added - Name longer than 200 chars"); + return false; + } if (!isLocalUnlockedUser(accounts.userId)) { Log.w(TAG, "Account " + account.toSafeString() + " cannot be added - user " + accounts.userId + " is locked. callingUid=" + callingUid); @@ -2065,6 +2073,10 @@ public class AccountManagerService + ", pid " + Binder.getCallingPid()); } if (accountToRename == null) throw new IllegalArgumentException("account is null"); + if (newName != null && newName.length() > 200) { + Log.e(TAG, "renameAccount failed - account name longer than 200"); + throw new IllegalArgumentException("account name longer than 200"); + } int userId = UserHandle.getCallingUserId(); if (!isAccountManagedByCaller(accountToRename.type, callingUid, userId)) { String msg = String.format( diff --git a/services/core/java/com/android/server/adb/AdbDebuggingManager.java b/services/core/java/com/android/server/adb/AdbDebuggingManager.java index 297d28dadde3..ad89afb791cc 100644 --- a/services/core/java/com/android/server/adb/AdbDebuggingManager.java +++ b/services/core/java/com/android/server/adb/AdbDebuggingManager.java @@ -892,15 +892,6 @@ public class AdbDebuggingManager { case MESSAGE_ADB_CONFIRM: { String key = (String) msg.obj; - if ("trigger_restart_min_framework".equals( - SystemProperties.get("vold.decrypt"))) { - Slog.w(TAG, "Deferring adb confirmation until after vold decrypt"); - if (mThread != null) { - mThread.sendResponse("NO"); - logAdbConnectionChanged(key, AdbProtoEnums.DENIED_VOLD_DECRYPT, false); - } - break; - } String fingerprints = getFingerprints(key); if ("".equals(fingerprints)) { if (mThread != null) { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index b9a55f990ce5..863e636d805b 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -412,6 +412,7 @@ import com.android.server.uri.GrantUri; import com.android.server.uri.NeededUriGrants; import com.android.server.uri.UriGrantsManagerInternal; import com.android.server.utils.PriorityDump; +import com.android.server.utils.Slogf; import com.android.server.utils.TimingsTraceAndSlog; import com.android.server.vr.VrManagerInternal; import com.android.server.wm.ActivityMetricsLaunchObserver; @@ -2264,13 +2265,9 @@ public class ActivityManagerService extends IActivityManager.Stub return mAppOpsManager; } - /** - * Provides the basic functionality for activity task related tests when a handler thread is - * given to initialize the dependency members. - */ + /** Provides the basic functionality for unit tests. */ @VisibleForTesting - public ActivityManagerService(Injector injector, ServiceThread handlerThread) { - final boolean hasHandlerThread = handlerThread != null; + ActivityManagerService(Injector injector, @NonNull ServiceThread handlerThread) { mInjector = injector; mContext = mInjector.getContext(); mUiContext = null; @@ -2278,33 +2275,27 @@ public class ActivityManagerService extends IActivityManager.Stub mPackageWatchdog = null; mAppOpsService = mInjector.getAppOpsService(null /* file */, null /* handler */); mBatteryStatsService = null; - mHandler = hasHandlerThread ? new MainHandler(handlerThread.getLooper()) : null; + mHandler = new MainHandler(handlerThread.getLooper()); mHandlerThread = handlerThread; - mConstants = hasHandlerThread - ? new ActivityManagerConstants(mContext, this, mHandler) : null; + mConstants = new ActivityManagerConstants(mContext, this, mHandler); final ActiveUids activeUids = new ActiveUids(this, false /* postChangesToAtm */); mPlatformCompat = null; mProcessList = injector.getProcessList(this); mProcessList.init(this, activeUids, mPlatformCompat); mAppProfiler = new AppProfiler(this, BackgroundThread.getHandler().getLooper(), null); mPhantomProcessList = new PhantomProcessList(this); - mOomAdjuster = hasHandlerThread - ? new OomAdjuster(this, mProcessList, activeUids, handlerThread) : null; + mOomAdjuster = new OomAdjuster(this, mProcessList, activeUids, handlerThread); - mIntentFirewall = hasHandlerThread - ? new IntentFirewall(new IntentFirewallInterface(), mHandler) : null; + mIntentFirewall = null; mProcessStats = null; mCpHelper = new ContentProviderHelper(this, false); - // For the usage of {@link ActiveServices#cleanUpServices} that may be invoked from - // {@link ActivityTaskSupervisor#cleanUpRemovedTaskLocked}. - mServices = hasHandlerThread ? new ActiveServices(this) : null; + mServices = null; mSystemThread = null; mUiHandler = injector.getUiHandler(null /* service */); mUidObserverController = new UidObserverController(mUiHandler); - mUserController = hasHandlerThread ? new UserController(this) : null; - mPendingIntentController = hasHandlerThread - ? new PendingIntentController(handlerThread.getLooper(), mUserController, - mConstants) : null; + mUserController = new UserController(this); + mPendingIntentController = + new PendingIntentController(handlerThread.getLooper(), mUserController, mConstants); mAppRestrictionController = new AppRestrictionController(mContext, this); mProcStartHandlerThread = null; mProcStartHandler = null; @@ -2312,7 +2303,7 @@ public class ActivityManagerService extends IActivityManager.Stub mFactoryTest = FACTORY_TEST_OFF; mUgmInternal = LocalServices.getService(UriGrantsManagerInternal.class); mInternal = new LocalService(); - mPendingStartActivityUids = new PendingStartActivityUids(mContext); + mPendingStartActivityUids = new PendingStartActivityUids(); mUseFifoUiScheduling = false; mEnableOffloadQueue = false; mFgBroadcastQueue = mBgBroadcastQueue = mBgOffloadBroadcastQueue = @@ -2447,7 +2438,7 @@ public class ActivityManagerService extends IActivityManager.Stub } mInternal = new LocalService(); - mPendingStartActivityUids = new PendingStartActivityUids(mContext); + mPendingStartActivityUids = new PendingStartActivityUids(); mTraceErrorLogger = new TraceErrorLogger(); mComponentAliasResolver = new ComponentAliasResolver(this); } @@ -4262,12 +4253,19 @@ public class ActivityManagerService extends IActivityManager.Stub intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); } + final int userId = UserHandle.getUserId(uid); + final int[] broadcastAllowList = + getPackageManagerInternal().getVisibilityAllowList(packageName, userId); intent.putExtra(Intent.EXTRA_UID, uid); - intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(uid)); - broadcastIntentLocked(null, null, null, intent, - null, null, 0, null, null, null, null, OP_NONE, - null, false, false, MY_PID, SYSTEM_UID, Binder.getCallingUid(), - Binder.getCallingPid(), UserHandle.getUserId(uid)); + intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); + broadcastIntentLocked(null /* callerApp */, null /* callerPackage */, + null /* callerFeatureId */, intent, null /* resolvedType */, null /* resultTo */, + 0 /* resultCode */, null /* resultData */, null /* resultExtras */, + null /* requiredPermissions */, null /* excludedPermissions */, OP_NONE, + null /* bOptions */, false /* ordered */, false /* sticky */, MY_PID, SYSTEM_UID, + Binder.getCallingUid(), Binder.getCallingPid(), userId, + false /* allowBackgroundActivityStarts */, null /* backgroundActivityStartsToken */, + broadcastAllowList); } private void cleanupDisabledPackageComponentsLocked( @@ -8721,8 +8719,8 @@ public class ActivityManagerService extends IActivityManager.Stub sb.append("Foreground: ") .append(process.isInterestingToUserLocked() ? "Yes" : "No") .append("\n"); - if (process.getStartTime() > 0) { - long runtimeMillis = SystemClock.elapsedRealtime() - process.getStartTime(); + if (process.getStartUptime() > 0) { + long runtimeMillis = SystemClock.uptimeMillis() - process.getStartUptime(); sb.append("Process-Runtime: ").append(runtimeMillis).append("\n"); } } @@ -9460,7 +9458,7 @@ public class ActivityManagerService extends IActivityManager.Stub opti++; } synchronized (this) { - dumpBroadcastsLocked(fd, pw, args, opti, true, dumpPackage); + dumpBroadcastsLocked(fd, pw, args, opti, /* dumpAll= */ true, dumpPackage); } } else if ("broadcast-stats".equals(cmd)) { if (opti < args.length) { @@ -10399,6 +10397,8 @@ public class ActivityManagerService extends IActivityManager.Stub boolean needSep = false; boolean onlyHistory = false; boolean printedAnything = false; + boolean onlyReceivers = false; + int filteredUid = Process.INVALID_UID; if ("history".equals(dumpPackage)) { if (opti < args.length && "-s".equals(args[opti])) { @@ -10407,6 +10407,31 @@ public class ActivityManagerService extends IActivityManager.Stub onlyHistory = true; dumpPackage = null; } + if ("receivers".equals(dumpPackage)) { + onlyReceivers = true; + dumpPackage = null; + if (opti + 2 <= args.length) { + for (int i = opti; i < args.length; i++) { + String arg = args[i]; + switch (arg) { + case "--uid": + filteredUid = getIntArg(pw, args, ++i, Process.INVALID_UID); + if (filteredUid == Process.INVALID_UID) { + return; + } + break; + default: + pw.printf("Invalid argument at index %d: %s\n", i, arg); + return; + } + } + } + } + if (DEBUG_BROADCAST) { + Slogf.d(TAG_BROADCAST, "dumpBroadcastsLocked(): dumpPackage=%s, onlyHistory=%b, " + + "onlyReceivers=%b, filteredUid=%d", dumpPackage, onlyHistory, onlyReceivers, + filteredUid); + } pw.println("ACTIVITY MANAGER BROADCAST STATE (dumpsys activity broadcasts)"); if (!onlyHistory && dumpAll) { @@ -10419,6 +10444,13 @@ public class ActivityManagerService extends IActivityManager.Stub !dumpPackage.equals(r.app.info.packageName))) { continue; } + if (filteredUid != Process.INVALID_UID && filteredUid != r.app.uid) { + if (DEBUG_BROADCAST) { + Slogf.v(TAG_BROADCAST, "dumpBroadcastsLocked(): skipping receiver whose" + + " uid (%d) is not %d: %s", r.app.uid, filteredUid, r.app); + } + continue; + } if (!printed) { pw.println(" Registered Receivers:"); needSep = true; @@ -10428,24 +10460,32 @@ public class ActivityManagerService extends IActivityManager.Stub pw.print(" * "); pw.println(r); r.dump(pw, " "); } + } else { + if (onlyReceivers) { + pw.println(" (no registered receivers)"); + } } - if (mReceiverResolver.dump(pw, needSep ? - "\n Receiver Resolver Table:" : " Receiver Resolver Table:", - " ", dumpPackage, false, false)) { - needSep = true; - printedAnything = true; + if (!onlyReceivers) { + if (mReceiverResolver.dump(pw, needSep + ? "\n Receiver Resolver Table:" : " Receiver Resolver Table:", + " ", dumpPackage, false, false)) { + needSep = true; + printedAnything = true; + } } } - for (BroadcastQueue q : mBroadcastQueues) { - needSep = q.dumpLocked(fd, pw, args, opti, dumpAll, dumpPackage, needSep); - printedAnything |= needSep; + if (!onlyReceivers) { + for (BroadcastQueue q : mBroadcastQueues) { + needSep = q.dumpLocked(fd, pw, args, opti, dumpAll, dumpPackage, needSep); + printedAnything |= needSep; + } } needSep = true; - if (!onlyHistory && mStickyBroadcasts != null && dumpPackage == null) { + if (!onlyHistory && !onlyReceivers && mStickyBroadcasts != null && dumpPackage == null) { for (int user=0; user<mStickyBroadcasts.size(); user++) { if (needSep) { pw.println(); @@ -10480,7 +10520,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } - if (!onlyHistory && dumpAll) { + if (!onlyHistory && !onlyReceivers && dumpAll) { pw.println(); for (BroadcastQueue queue : mBroadcastQueues) { pw.println(" mBroadcastsScheduled [" + queue.mQueueName + "]=" @@ -17263,7 +17303,7 @@ public class ActivityManagerService extends IActivityManager.Stub // next top activity on time. This race will fail the following binder transactions WM // sends to the activity. After this race issue between WM/ATMS and AMS is solved, this // workaround can be removed. (b/213288355) - if (isNewPending && mOomAdjuster != null) { // It can be null in unit test. + if (isNewPending) { mOomAdjuster.mCachedAppOptimizer.unfreezeProcess(pid); } // We need to update the network rules for the app coming to the top state so that @@ -18360,4 +18400,24 @@ public class ActivityManagerService extends IActivityManager.Stub Trace.traceBegin(traceTag, methodName + subInfo); } } + + /** + * Gets an {@code int} argument from the given {@code index} on {@code args}, logging an error + * message on {@code pw} when it cannot be parsed. + * + * Returns {@code int} argument or {@code invalidValue} if it could not be parsed. + */ + private static int getIntArg(PrintWriter pw, String[] args, int index, int invalidValue) { + if (index > args.length) { + pw.println("Missing argument"); + return invalidValue; + } + String arg = args[index]; + try { + return Integer.parseInt(arg); + } catch (Exception e) { + pw.printf("Non-numeric argument at index %d: %s\n", index, arg); + return invalidValue; + } + } } diff --git a/services/core/java/com/android/server/am/PendingStartActivityUids.java b/services/core/java/com/android/server/am/PendingStartActivityUids.java index bd600571f0a3..da09317add90 100644 --- a/services/core/java/com/android/server/am/PendingStartActivityUids.java +++ b/services/core/java/com/android/server/am/PendingStartActivityUids.java @@ -16,7 +16,6 @@ package com.android.server.am; -import android.content.Context; import android.os.SystemClock; import android.util.Pair; import android.util.Slog; @@ -40,11 +39,6 @@ final class PendingStartActivityUids { // Key is uid, value is Pair of pid and SystemClock.elapsedRealtime() when the // uid is added. private final SparseArray<Pair<Integer, Long>> mPendingUids = new SparseArray(); - private Context mContext; - - PendingStartActivityUids(Context context) { - mContext = context; - } /** Returns {@code true} if the uid is put to the pending array. Otherwise it existed. */ synchronized boolean add(int uid, int pid) { diff --git a/services/core/java/com/android/server/am/ReceiverList.java b/services/core/java/com/android/server/am/ReceiverList.java index ff34fd36de3e..f3d8ba1564fa 100644 --- a/services/core/java/com/android/server/am/ReceiverList.java +++ b/services/core/java/com/android/server/am/ReceiverList.java @@ -16,6 +16,7 @@ package com.android.server.am; +import android.annotation.Nullable; import android.content.IIntentReceiver; import android.content.IntentFilter; import android.os.Binder; @@ -37,7 +38,7 @@ final class ReceiverList extends ArrayList<BroadcastFilter> implements IBinder.DeathRecipient { final ActivityManagerService owner; public final IIntentReceiver receiver; - public final ProcessRecord app; + public final @Nullable ProcessRecord app; public final int pid; public final int uid; public final int userId; @@ -46,7 +47,7 @@ final class ReceiverList extends ArrayList<BroadcastFilter> String stringName; - ReceiverList(ActivityManagerService _owner, ProcessRecord _app, + ReceiverList(ActivityManagerService _owner, @Nullable ProcessRecord _app, int _pid, int _uid, int _userId, IIntentReceiver _receiver) { owner = _owner; receiver = _receiver; @@ -82,7 +83,10 @@ final class ReceiverList extends ArrayList<BroadcastFilter> void dumpDebug(ProtoOutputStream proto, long fieldId) { long token = proto.start(fieldId); - app.dumpDebug(proto, ReceiverListProto.APP); + if (app != null) { + app.dumpDebug(proto, ReceiverListProto.APP); + proto.write(ReceiverListProto.NUMBER_RECEIVERS, app.mReceivers.numberOfReceivers()); + } proto.write(ReceiverListProto.PID, pid); proto.write(ReceiverListProto.UID, uid); proto.write(ReceiverListProto.USER, userId); @@ -101,8 +105,12 @@ final class ReceiverList extends ArrayList<BroadcastFilter> void dumpLocal(PrintWriter pw, String prefix) { pw.print(prefix); pw.print("app="); pw.print(app != null ? app.toShortString() : null); - pw.print(" pid="); pw.print(pid); pw.print(" uid="); pw.print(uid); - pw.print(" user="); pw.println(userId); + pw.print(" pid="); pw.print(pid); pw.print(" uid="); pw.print(uid); + pw.print(" user="); pw.print(userId); + if (app != null) { + pw.print(" #receivers="); pw.print(app.mReceivers.numberOfReceivers()); + } + pw.println(); if (curBroadcast != null || linkedToDeath) { pw.print(prefix); pw.print("curBroadcast="); pw.print(curBroadcast); pw.print(" linkedToDeath="); pw.println(linkedToDeath); diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java index 361629b0a629..f35d7929a8f7 100644 --- a/services/core/java/com/android/server/appop/AppOpsService.java +++ b/services/core/java/com/android/server/appop/AppOpsService.java @@ -2783,7 +2783,9 @@ public class AppOpsService extends IAppOpsService.Stub { @Nullable IAppOpsCallback permissionPolicyCallback) { enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid); verifyIncomingOp(code); - verifyIncomingPackage(packageName, UserHandle.getUserId(uid)); + if (!isIncomingPackageValid(packageName, UserHandle.getUserId(uid))) { + return; + } ArraySet<ModeCallback> repCbs = null; code = AppOpsManager.opToSwitch(code); @@ -3218,7 +3220,9 @@ public class AppOpsService extends IAppOpsService.Stub { private int checkOperationImpl(int code, int uid, String packageName, @Nullable String attributionTag, boolean raw) { verifyIncomingOp(code); - verifyIncomingPackage(packageName, UserHandle.getUserId(uid)); + if (!isIncomingPackageValid(packageName, UserHandle.getUserId(uid))) { + return AppOpsManager.opToDefaultMode(code); + } String resolvedPackageName = AppOpsManager.resolvePackageName(uid, packageName); if (resolvedPackageName == null) { @@ -3330,8 +3334,7 @@ public class AppOpsService extends IAppOpsService.Stub { } private boolean isPackageExisted(String packageName) { - return LocalServices.getService(PackageManagerInternal.class) - .getPackageStateInternal(packageName) != null; + return getPackageManagerInternal().getPackageStateInternal(packageName) != null; } /** @@ -3366,8 +3369,11 @@ public class AppOpsService extends IAppOpsService.Stub { verifyIncomingProxyUid(attributionSource); verifyIncomingOp(code); - verifyIncomingPackage(proxiedPackageName, UserHandle.getUserId(proxiedUid)); - verifyIncomingPackage(proxyPackageName, UserHandle.getUserId(proxyUid)); + if (!isIncomingPackageValid(proxiedPackageName, UserHandle.getUserId(proxiedUid)) + || !isIncomingPackageValid(proxyPackageName, UserHandle.getUserId(proxyUid))) { + return new SyncNotedAppOp(AppOpsManager.MODE_ERRORED, code, proxiedAttributionTag, + proxiedPackageName); + } skipProxyOperation = skipProxyOperation && isCallerAndAttributionTrusted(attributionSource); @@ -3424,7 +3430,10 @@ public class AppOpsService extends IAppOpsService.Stub { @Nullable String message, boolean shouldCollectMessage) { verifyIncomingUid(uid); verifyIncomingOp(code); - verifyIncomingPackage(packageName, UserHandle.getUserId(uid)); + if (!isIncomingPackageValid(packageName, UserHandle.getUserId(uid))) { + return new SyncNotedAppOp(AppOpsManager.MODE_ERRORED, code, attributionTag, + packageName); + } String resolvedPackageName = AppOpsManager.resolvePackageName(uid, packageName); if (resolvedPackageName == null) { @@ -3830,7 +3839,10 @@ public class AppOpsService extends IAppOpsService.Stub { int attributionChainId) { verifyIncomingUid(uid); verifyIncomingOp(code); - verifyIncomingPackage(packageName, UserHandle.getUserId(uid)); + if (!isIncomingPackageValid(packageName, UserHandle.getUserId(uid))) { + return new SyncNotedAppOp(AppOpsManager.MODE_ERRORED, code, attributionTag, + packageName); + } String resolvedPackageName = AppOpsManager.resolvePackageName(uid, packageName); if (resolvedPackageName == null) { @@ -3884,8 +3896,11 @@ public class AppOpsService extends IAppOpsService.Stub { verifyIncomingProxyUid(attributionSource); verifyIncomingOp(code); - verifyIncomingPackage(proxyPackageName, UserHandle.getUserId(proxyUid)); - verifyIncomingPackage(proxiedPackageName, UserHandle.getUserId(proxiedUid)); + if (!isIncomingPackageValid(proxyPackageName, UserHandle.getUserId(proxyUid)) + || !isIncomingPackageValid(proxiedPackageName, UserHandle.getUserId(proxiedUid))) { + return new SyncNotedAppOp(AppOpsManager.MODE_ERRORED, code, proxiedAttributionTag, + proxiedPackageName); + } boolean isCallerTrusted = isCallerAndAttributionTrusted(attributionSource); skipProxyOperation = isCallerTrusted && skipProxyOperation; @@ -4070,7 +4085,9 @@ public class AppOpsService extends IAppOpsService.Stub { String attributionTag) { verifyIncomingUid(uid); verifyIncomingOp(code); - verifyIncomingPackage(packageName, UserHandle.getUserId(uid)); + if (!isIncomingPackageValid(packageName, UserHandle.getUserId(uid))) { + return; + } String resolvedPackageName = AppOpsManager.resolvePackageName(uid, packageName); if (resolvedPackageName == null) { @@ -4103,8 +4120,10 @@ public class AppOpsService extends IAppOpsService.Stub { verifyIncomingProxyUid(attributionSource); verifyIncomingOp(code); - verifyIncomingPackage(proxyPackageName, UserHandle.getUserId(proxyUid)); - verifyIncomingPackage(proxiedPackageName, UserHandle.getUserId(proxiedUid)); + if (!isIncomingPackageValid(proxyPackageName, UserHandle.getUserId(proxyUid)) + || !isIncomingPackageValid(proxiedPackageName, UserHandle.getUserId(proxiedUid))) { + return null; + } String resolvedProxyPackageName = AppOpsManager.resolvePackageName(proxyUid, proxyPackageName); @@ -4377,12 +4396,32 @@ public class AppOpsService extends IAppOpsService.Stub { throw new IllegalArgumentException("Bad operation #" + op); } - private void verifyIncomingPackage(@Nullable String packageName, @UserIdInt int userId) { - if (packageName != null && getPackageManagerInternal().filterAppAccess(packageName, - Binder.getCallingUid(), userId)) { - throw new IllegalArgumentException( - packageName + " not found from " + Binder.getCallingUid()); + private boolean isIncomingPackageValid(@Nullable String packageName, @UserIdInt int userId) { + final int callingUid = Binder.getCallingUid(); + // Handle the special UIDs that don't have actual packages (audioserver, cameraserver, etc). + if (packageName == null || isSpecialPackage(callingUid, packageName)) { + return true; } + + // If the package doesn't exist, #verifyAndGetBypass would throw a SecurityException in + // the end. Although that exception would be caught and return, we could make it return + // early. + if (!isPackageExisted(packageName)) { + return false; + } + + if (getPackageManagerInternal().filterAppAccess(packageName, callingUid, userId)) { + Slog.w(TAG, packageName + " not found from " + callingUid); + return false; + } + + return true; + } + + private boolean isSpecialPackage(int callingUid, @Nullable String packageName) { + final String resolvedPackage = AppOpsManager.resolvePackageName(callingUid, packageName); + return callingUid == Process.SYSTEM_UID + || resolveUid(resolvedPackage) != Process.INVALID_UID; } private boolean isCallerAndAttributionTrusted(@NonNull AttributionSource attributionSource) { @@ -6672,7 +6711,9 @@ public class AppOpsService extends IAppOpsService.Stub { } } verifyIncomingOp(code); - verifyIncomingPackage(packageName, UserHandle.getUserId(uid)); + if (!isIncomingPackageValid(packageName, UserHandle.getUserId(uid))) { + return false; + } final String resolvedPackageName = AppOpsManager.resolvePackageName(uid, packageName); if (resolvedPackageName == null) { @@ -7077,7 +7118,7 @@ public class AppOpsService extends IAppOpsService.Stub { private static int resolveUid(String packageName) { if (packageName == null) { - return -1; + return Process.INVALID_UID; } switch (packageName) { case "root": @@ -7092,7 +7133,7 @@ public class AppOpsService extends IAppOpsService.Stub { case "cameraserver": return Process.CAMERASERVER_UID; } - return -1; + return Process.INVALID_UID; } private static String[] getPackagesForUid(int uid) { diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java index 0d9b75481ea9..4767969bd3ed 100644 --- a/services/core/java/com/android/server/biometrics/BiometricService.java +++ b/services/core/java/com/android/server/biometrics/BiometricService.java @@ -958,7 +958,7 @@ public class BiometricService extends SystemService { public boolean isCoexFaceNonBypassHapticsDisabled(Context context) { return Settings.Secure.getInt(context.getContentResolver(), - CoexCoordinator.FACE_HAPTIC_DISABLE, 1) != 0; + CoexCoordinator.FACE_HAPTIC_DISABLE, 0) != 0; } public Supplier<Long> getRequestGenerator() { diff --git a/services/core/java/com/android/server/biometrics/Utils.java b/services/core/java/com/android/server/biometrics/Utils.java index 0e2582c23b86..e1ef277a2b8a 100644 --- a/services/core/java/com/android/server/biometrics/Utils.java +++ b/services/core/java/com/android/server/biometrics/Utils.java @@ -53,6 +53,7 @@ import android.hardware.biometrics.SensorProperties; import android.hardware.biometrics.SensorPropertiesInternal; import android.os.Binder; import android.os.Build; +import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; @@ -87,6 +88,13 @@ public class Utils { return true; } + /** If virtualized biometrics are supported (requires debug build). */ + public static boolean isVirtualEnabled(Context context) { + return Build.isDebuggable() + && Settings.Secure.getIntForUser(context.getContentResolver(), + Settings.Secure.BIOMETRIC_VIRTUAL_ENABLED, 0, UserHandle.USER_CURRENT) == 1; + } + /** * Combines {@link PromptInfo#setDeviceCredentialAllowed(boolean)} with * {@link PromptInfo#setAuthenticators(int)}, as the former is not flexible enough. @@ -374,6 +382,15 @@ public class Utils { return false; } + /** Same as checkPermission but also allows shell. */ + public static void checkPermissionOrShell(Context context, String permission) { + if (Binder.getCallingUid() == Process.SHELL_UID) { + return; + } + checkPermission(context, permission); + } + + public static void checkPermission(Context context, String permission) { context.enforceCallingOrSelfPermission(permission, "Must have " + permission + " permission."); diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java index 6d687726dbe8..1002229518e4 100644 --- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java @@ -105,7 +105,7 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T> mIsStrongBiometric = isStrongBiometric; mOperationId = operationId; mRequireConfirmation = requireConfirmation; - mActivityTaskManager = ActivityTaskManager.getInstance(); + mActivityTaskManager = getActivityTaskManager(); mBiometricManager = context.getSystemService(BiometricManager.class); mTaskStackListener = taskStackListener; mLockoutTracker = lockoutTracker; @@ -133,6 +133,10 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T> return mStartTimeMs; } + protected ActivityTaskManager getActivityTaskManager() { + return ActivityTaskManager.getInstance(); + } + @Override public void binderDied() { final boolean clearListener = !isBiometricPrompt(); @@ -310,45 +314,50 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T> sendCancelOnly(listener); } }); - } else { - // Allow system-defined limit of number of attempts before giving up - final @LockoutTracker.LockoutMode int lockoutMode = - handleFailedAttempt(getTargetUserId()); - if (lockoutMode != LockoutTracker.LOCKOUT_NONE) { - markAlreadyDone(); - } - - final CoexCoordinator coordinator = CoexCoordinator.getInstance(); - coordinator.onAuthenticationRejected(SystemClock.uptimeMillis(), this, lockoutMode, - new CoexCoordinator.Callback() { - @Override - public void sendAuthenticationResult(boolean addAuthTokenIfStrong) { - if (listener != null) { - try { - listener.onAuthenticationFailed(getSensorId()); - } catch (RemoteException e) { - Slog.e(TAG, "Unable to notify listener", e); - } - } + } else { // not authenticated + if (isBackgroundAuth) { + Slog.e(TAG, "cancelling due to background auth"); + cancel(); + } else { + // Allow system-defined limit of number of attempts before giving up + final @LockoutTracker.LockoutMode int lockoutMode = + handleFailedAttempt(getTargetUserId()); + if (lockoutMode != LockoutTracker.LOCKOUT_NONE) { + markAlreadyDone(); } - @Override - public void sendHapticFeedback() { - if (listener != null && mShouldVibrate) { - vibrateError(); - } - } + final CoexCoordinator coordinator = CoexCoordinator.getInstance(); + coordinator.onAuthenticationRejected(SystemClock.uptimeMillis(), this, lockoutMode, + new CoexCoordinator.Callback() { + @Override + public void sendAuthenticationResult(boolean addAuthTokenIfStrong) { + if (listener != null) { + try { + listener.onAuthenticationFailed(getSensorId()); + } catch (RemoteException e) { + Slog.e(TAG, "Unable to notify listener", e); + } + } + } - @Override - public void handleLifecycleAfterAuth() { - AuthenticationClient.this.handleLifecycleAfterAuth(false /* authenticated */); - } + @Override + public void sendHapticFeedback() { + if (listener != null && mShouldVibrate) { + vibrateError(); + } + } - @Override - public void sendAuthenticationCanceled() { - sendCancelOnly(listener); - } - }); + @Override + public void handleLifecycleAfterAuth() { + AuthenticationClient.this.handleLifecycleAfterAuth(false /* authenticated */); + } + + @Override + public void sendAuthenticationCanceled() { + sendCancelOnly(listener); + } + }); + } } } 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 57ea812dbb3a..ded9c8de4dba 100644 --- a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java @@ -19,9 +19,11 @@ package com.android.server.biometrics.sensors; import android.annotation.NonNull; import android.content.Context; import android.hardware.biometrics.BiometricAuthenticator; +import android.os.Build; import android.os.IBinder; import android.util.Slog; +import com.android.internal.annotations.VisibleForTesting; import com.android.server.biometrics.BiometricsProto; import com.android.server.biometrics.log.BiometricContext; import com.android.server.biometrics.log.BiometricLogger; @@ -65,6 +67,7 @@ public abstract class InternalCleanupClient<S extends BiometricAuthenticator.Ide private final List<S> mEnrolledList; private final boolean mHasEnrollmentsBeforeStarting; private BaseClientMonitor mCurrentTask; + private boolean mFavorHalEnrollments = false; private final ClientMonitorCallback mEnumerateCallback = new ClientMonitorCallback() { @Override @@ -87,7 +90,21 @@ public abstract class InternalCleanupClient<S extends BiometricAuthenticator.Ide // InternalEnumerateClient. Finish this client. mCallback.onClientFinished(InternalCleanupClient.this, success); } else { - startCleanupUnknownHalTemplates(); + if (mFavorHalEnrollments && Build.isDebuggable()) { + // on debug builds, optionally allow the HAL be the source of + // truth for enrollments + try { + for (UserTemplate template : mUnknownHALTemplates) { + Slog.i(TAG, "Adding unknown HAL template: " + + template.mIdentifier.getBiometricId()); + onAddUnknownTemplate(template.mUserId, template.mIdentifier); + } + } finally { + mCallback.onClientFinished(InternalCleanupClient.this, success); + } + } else { + startCleanupUnknownHalTemplates(); + } } } }; @@ -197,8 +214,27 @@ public abstract class InternalCleanupClient<S extends BiometricAuthenticator.Ide ((EnumerateConsumer) mCurrentTask).onEnumerationResult(identifier, remaining); } + /** When set unknown templates in the HAL will be added instead of deleted. */ + public void setFavorHalEnrollments() { + mFavorHalEnrollments = true; + } + + /** Called when an unknown template is found and setFavorHalEnrollments was requested. */ + protected void onAddUnknownTemplate(int userId, + @NonNull BiometricAuthenticator.Identifier identifier) {} + @Override public int getProtoEnum() { return BiometricsProto.CM_INTERNAL_CLEANUP; } + + @VisibleForTesting + public InternalEnumerateClient<T> getCurrentEnumerateClient() { + return (InternalEnumerateClient<T>) mCurrentTask; + } + + @VisibleForTesting + public RemovalClient<S, T> getCurrentRemoveClient() { + return (RemovalClient<S, T>) mCurrentTask; + } } diff --git a/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java b/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java index e0d519469e32..45ffa23dc66a 100644 --- a/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java @@ -50,8 +50,6 @@ public abstract class RemovalClient<S extends BiometricAuthenticator.Identifier, @NonNull Map<Integer, Long> authenticatorIds) { super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId, logger, biometricContext); - //, BiometricsProtoEnums.ACTION_REMOVE, - // BiometricsProtoEnums.CLIENT_UNKNOWN); mBiometricUtils = utils; mAuthenticatorIds = authenticatorIds; mHasEnrollmentsBeforeStarting = !utils.getBiometricsForUser(context, userId).isEmpty(); diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInternalCleanupClient.java index 54f2033b363a..b0b23faa9aa5 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInternalCleanupClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInternalCleanupClient.java @@ -18,6 +18,7 @@ package com.android.server.biometrics.sensors.face.aidl; import android.annotation.NonNull; import android.content.Context; +import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.face.IFace; import android.hardware.face.Face; import android.os.IBinder; @@ -28,6 +29,7 @@ import com.android.server.biometrics.sensors.BiometricUtils; import com.android.server.biometrics.sensors.InternalCleanupClient; import com.android.server.biometrics.sensors.InternalEnumerateClient; import com.android.server.biometrics.sensors.RemovalClient; +import com.android.server.biometrics.sensors.face.FaceUtils; import java.util.List; import java.util.Map; @@ -68,4 +70,11 @@ class FaceInternalCleanupClient extends InternalCleanupClient<Face, AidlSession> null /* ClientMonitorCallbackConverter */, new int[] {biometricId}, userId, owner, utils, sensorId, logger, biometricContext, authenticatorIds); } + + @Override + protected void onAddUnknownTemplate(int userId, + @NonNull BiometricAuthenticator.Identifier identifier) { + FaceUtils.getInstance(getSensorId()).addBiometricForUser( + getContext(), getTargetUserId(), (Face) identifier); + } } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java index 97efc7813230..9b098cab998a 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java @@ -32,6 +32,7 @@ import static android.hardware.biometrics.SensorProperties.STRENGTH_STRONG; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.ActivityManager; import android.app.AppOpsManager; import android.content.Context; import android.content.pm.PackageManager; @@ -67,7 +68,9 @@ import android.os.Looper; import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; +import android.os.ResultReceiver; import android.os.ServiceManager; +import android.os.ShellCallback; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; @@ -344,12 +347,12 @@ public class FingerprintService extends SystemService { provider.second.getSensorProperties(sensorId); if (!isKeyguard && !Utils.isSettings(getContext(), opPackageName) && sensorProps != null && sensorProps.isAnyUdfpsType()) { - final long identity2 = Binder.clearCallingIdentity(); try { return authenticateWithPrompt(operationId, sensorProps, userId, receiver, - ignoreEnrollmentState); - } finally { - Binder.restoreCallingIdentity(identity2); + opPackageName, ignoreEnrollmentState); + } catch (PackageManager.NameNotFoundException e) { + Slog.e(TAG, "Invalid package", e); + return -1; } } return provider.second.scheduleAuthenticate(provider.first, token, operationId, userId, @@ -362,12 +365,15 @@ public class FingerprintService extends SystemService { @NonNull final FingerprintSensorPropertiesInternal props, final int userId, final IFingerprintServiceReceiver receiver, - boolean ignoreEnrollmentState) { + final String opPackageName, + boolean ignoreEnrollmentState) throws PackageManager.NameNotFoundException { final Context context = getUiContext(); + final Context promptContext = context.createPackageContextAsUser( + opPackageName, 0 /* flags */, UserHandle.getUserHandleForUid(userId)); final Executor executor = context.getMainExecutor(); - final BiometricPrompt biometricPrompt = new BiometricPrompt.Builder(context) + final BiometricPrompt biometricPrompt = new BiometricPrompt.Builder(promptContext) .setTitle(context.getString(R.string.biometric_dialog_default_title)) .setSubtitle(context.getString(R.string.fingerprint_dialog_default_subtitle)) .setNegativeButton( @@ -381,8 +387,7 @@ public class FingerprintService extends SystemService { Slog.e(TAG, "Remote exception in negative button onClick()", e); } }) - .setAllowedSensorIds(new ArrayList<>( - Collections.singletonList(props.sensorId))) + .setIsForLegacyFingerprintManager(props.sensorId) .setIgnoreEnrollmentState(ignoreEnrollmentState) .build(); @@ -436,8 +441,8 @@ public class FingerprintService extends SystemService { } }; - return biometricPrompt.authenticateUserForOperation( - new CancellationSignal(), executor, promptCallback, userId, operationId); + return biometricPrompt.authenticateForOperation( + new CancellationSignal(), executor, promptCallback, operationId); } @Override @@ -622,6 +627,15 @@ public class FingerprintService extends SystemService { } @Override // Binder call + public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out, + @Nullable FileDescriptor err, @NonNull String[] args, + @Nullable ShellCallback callback, @NonNull ResultReceiver resultReceiver) + throws RemoteException { + (new FingerprintShellCommand(getContext(), FingerprintService.this)) + .exec(this, in, out, err, args, callback, resultReceiver); + } + + @Override // Binder call protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, String[] args) { if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) { return; @@ -1173,4 +1187,18 @@ public class FingerprintService extends SystemService { } return appOpsOk; } + + void syncEnrollmentsNow() { + Utils.checkPermissionOrShell(getContext(), MANAGE_FINGERPRINT); + if (Utils.isVirtualEnabled(getContext())) { + Slog.i(TAG, "Sync virtual enrollments"); + final int userId = ActivityManager.getCurrentUser(); + for (ServiceProvider provider : mServiceProviders) { + for (FingerprintSensorPropertiesInternal props : provider.getSensorProperties()) { + provider.scheduleInternalCleanup(props.sensorId, userId, null /* callback */, + true /* favorHalEnrollments */); + } + } + } + } } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintShellCommand.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintShellCommand.java new file mode 100644 index 000000000000..636413f75cf5 --- /dev/null +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintShellCommand.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.biometrics.sensors.fingerprint; + +import android.content.Context; +import android.os.ShellCommand; + +import java.io.PrintWriter; + +/** Handles shell commands for {@link FingerprintService}. */ +public class FingerprintShellCommand extends ShellCommand { + + private final Context mContext; + private final FingerprintService mService; + + public FingerprintShellCommand(Context context, FingerprintService service) { + mContext = context; + mService = service; + } + + @Override + public int onCommand(String cmd) { + if (cmd == null) { + onHelp(); + return 1; + } + + try { + switch (cmd) { + case "help": + return doHelp(); + case "sync": + return doSync(); + default: + getOutPrintWriter().println("Unrecognized command: " + cmd); + } + } catch (Exception e) { + getOutPrintWriter().println("Exception: " + e); + } + return -1; + } + + @Override + public void onHelp() { + PrintWriter pw = getOutPrintWriter(); + pw.println("Fingerprint Service commands:"); + pw.println(" help"); + pw.println(" Print this help text."); + pw.println(" sync"); + pw.println(" Sync enrollments now (virtualized sensors only)."); + } + + private int doHelp() { + onHelp(); + return 0; + } + + private int doSync() { + mService.syncEnrollmentsNow(); + return 0; + } +} diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java index 9cdbdc9158fb..4dfc73872014 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java @@ -123,6 +123,9 @@ public interface ServiceProvider { void scheduleInternalCleanup(int sensorId, int userId, @Nullable ClientMonitorCallback callback); + void scheduleInternalCleanup(int sensorId, int userId, + @Nullable ClientMonitorCallback callback, boolean favorHalEnrollments); + boolean isHardwareDetected(int sensorId); void rename(int sensorId, int fingerId, int userId, @NonNull String name); diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClient.java index 09bdd6de49f0..c315ccf8dea2 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClient.java @@ -18,6 +18,7 @@ package com.android.server.biometrics.sensors.fingerprint.aidl; import android.annotation.NonNull; import android.content.Context; +import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricsProtoEnums; import android.hardware.fingerprint.Fingerprint; import android.os.IBinder; @@ -72,4 +73,11 @@ class FingerprintInternalCleanupClient extends InternalCleanupClient<Fingerprint utils, sensorId, logger.swapAction(context, BiometricsProtoEnums.ACTION_REMOVE), biometricContext, authenticatorIds); } + + @Override + protected void onAddUnknownTemplate(int userId, + @NonNull BiometricAuthenticator.Identifier identifier) { + FingerprintUtils.getInstance(getSensorId()).addBiometricForUser( + getContext(), getTargetUserId(), (Fingerprint) identifier); + } } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java index 7d5b77c2d711..ecc3882ced4f 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java @@ -516,6 +516,12 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi @Override public void scheduleInternalCleanup(int sensorId, int userId, @Nullable ClientMonitorCallback callback) { + scheduleInternalCleanup(sensorId, userId, callback, false /* favorHalEnrollments */); + } + + @Override + public void scheduleInternalCleanup(int sensorId, int userId, + @Nullable ClientMonitorCallback callback, boolean favorHalEnrollments) { mHandler.post(() -> { final List<Fingerprint> enrolledList = getEnrolledFingerprints(sensorId, userId); final FingerprintInternalCleanupClient client = @@ -527,6 +533,9 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi mBiometricContext, enrolledList, FingerprintUtils.getInstance(sensorId), mSensors.get(sensorId).getAuthenticatorIds()); + if (favorHalEnrollments) { + client.setFavorHalEnrollments(); + } scheduleForSensor(sensorId, client, new ClientMonitorCompositeCallback(callback, mBiometricStateCallback)); }); diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java index 52dbe2460e1c..6ca94b75307a 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java @@ -757,6 +757,13 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider mBiometricStateCallback)); } + @Override + public void scheduleInternalCleanup(int sensorId, int userId, + @Nullable ClientMonitorCallback callback, boolean favorHalEnrollments) { + scheduleInternalCleanup(userId, new ClientMonitorCompositeCallback(callback, + mBiometricStateCallback)); + } + private BiometricLogger createLogger(int statsAction, int statsClient) { return new BiometricLogger(mContext, BiometricsProtoEnums.MODALITY_FINGERPRINT, statsAction, statsClient); diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java index aab6281e6cd1..387e00f73932 100644 --- a/services/core/java/com/android/server/compat/PlatformCompat.java +++ b/services/core/java/com/android/server/compat/PlatformCompat.java @@ -20,9 +20,9 @@ import static android.Manifest.permission.LOG_COMPAT_CHANGE; import static android.Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG; import static android.Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD; import static android.Manifest.permission.READ_COMPAT_CHANGE_CONFIG; -import static android.content.pm.PackageManager.PERMISSION_GRANTED; -import static android.os.Process.SYSTEM_UID; +import android.annotation.EnforcePermission; +import android.annotation.RequiresNoPermission; import android.annotation.UserIdInt; import android.app.ActivityManager; import android.app.IActivityManager; @@ -93,15 +93,15 @@ public class PlatformCompat extends IPlatformCompat.Stub { } @Override + @EnforcePermission(LOG_COMPAT_CHANGE) public void reportChange(long changeId, ApplicationInfo appInfo) { - checkCompatChangeLogPermission(); reportChangeInternal(changeId, appInfo.uid, ChangeReporter.STATE_LOGGED); } @Override + @EnforcePermission(LOG_COMPAT_CHANGE) public void reportChangeByPackageName(long changeId, String packageName, @UserIdInt int userId) { - checkCompatChangeLogPermission(); ApplicationInfo appInfo = getApplicationInfo(packageName, userId); if (appInfo != null) { reportChangeInternal(changeId, appInfo.uid, ChangeReporter.STATE_LOGGED); @@ -109,8 +109,8 @@ public class PlatformCompat extends IPlatformCompat.Stub { } @Override + @EnforcePermission(LOG_COMPAT_CHANGE) public void reportChangeByUid(long changeId, int uid) { - checkCompatChangeLogPermission(); reportChangeInternal(changeId, uid, ChangeReporter.STATE_LOGGED); } @@ -119,15 +119,15 @@ public class PlatformCompat extends IPlatformCompat.Stub { } @Override + @EnforcePermission(allOf = {LOG_COMPAT_CHANGE, READ_COMPAT_CHANGE_CONFIG}) public boolean isChangeEnabled(long changeId, ApplicationInfo appInfo) { - checkCompatChangeReadAndLogPermission(); return isChangeEnabledInternal(changeId, appInfo); } @Override + @EnforcePermission(allOf = {LOG_COMPAT_CHANGE, READ_COMPAT_CHANGE_CONFIG}) public boolean isChangeEnabledByPackageName(long changeId, String packageName, @UserIdInt int userId) { - checkCompatChangeReadAndLogPermission(); ApplicationInfo appInfo = getApplicationInfo(packageName, userId); if (appInfo == null) { return mCompatConfig.willChangeBeEnabled(changeId, packageName); @@ -136,8 +136,8 @@ public class PlatformCompat extends IPlatformCompat.Stub { } @Override + @EnforcePermission(allOf = {LOG_COMPAT_CHANGE, READ_COMPAT_CHANGE_CONFIG}) public boolean isChangeEnabledByUid(long changeId, int uid) { - checkCompatChangeReadAndLogPermission(); String[] packages = mContext.getPackageManager().getPackagesForUid(uid); if (packages == null || packages.length == 0) { return mCompatConfig.defaultChangeIdValue(changeId); @@ -197,8 +197,8 @@ public class PlatformCompat extends IPlatformCompat.Stub { } @Override + @EnforcePermission(OVERRIDE_COMPAT_CHANGE_CONFIG) public void setOverrides(CompatibilityChangeConfig overrides, String packageName) { - checkCompatChangeOverridePermission(); Map<Long, PackageOverride> overridesMap = new HashMap<>(); for (long change : overrides.enabledChanges()) { overridesMap.put(change, new PackageOverride.Builder().setEnabled(true).build()); @@ -213,8 +213,8 @@ public class PlatformCompat extends IPlatformCompat.Stub { } @Override + @EnforcePermission(OVERRIDE_COMPAT_CHANGE_CONFIG) public void setOverridesForTest(CompatibilityChangeConfig overrides, String packageName) { - checkCompatChangeOverridePermission(); Map<Long, PackageOverride> overridesMap = new HashMap<>(); for (long change : overrides.enabledChanges()) { overridesMap.put(change, new PackageOverride.Builder().setEnabled(true).build()); @@ -228,9 +228,9 @@ public class PlatformCompat extends IPlatformCompat.Stub { } @Override + @EnforcePermission(OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD) public void putAllOverridesOnReleaseBuilds( CompatibilityOverridesByPackageConfig overridesByPackage) { - checkCompatChangeOverrideOverridablePermission(); for (CompatibilityOverrideConfig overrides : overridesByPackage.packageNameToOverrides.values()) { checkAllCompatOverridesAreOverridable(overrides.overrides.keySet()); @@ -239,16 +239,16 @@ public class PlatformCompat extends IPlatformCompat.Stub { } @Override + @EnforcePermission(OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD) public void putOverridesOnReleaseBuilds(CompatibilityOverrideConfig overrides, String packageName) { - checkCompatChangeOverrideOverridablePermission(); checkAllCompatOverridesAreOverridable(overrides.overrides.keySet()); mCompatConfig.addPackageOverrides(overrides, packageName, /* skipUnknownChangeIds= */ true); } @Override + @EnforcePermission(OVERRIDE_COMPAT_CHANGE_CONFIG) public int enableTargetSdkChanges(String packageName, int targetSdkVersion) { - checkCompatChangeOverridePermission(); int numChanges = mCompatConfig.enableTargetSdkChangesForPackage(packageName, targetSdkVersion); killPackage(packageName); @@ -256,8 +256,8 @@ public class PlatformCompat extends IPlatformCompat.Stub { } @Override + @EnforcePermission(OVERRIDE_COMPAT_CHANGE_CONFIG) public int disableTargetSdkChanges(String packageName, int targetSdkVersion) { - checkCompatChangeOverridePermission(); int numChanges = mCompatConfig.disableTargetSdkChangesForPackage(packageName, targetSdkVersion); killPackage(packageName); @@ -265,36 +265,36 @@ public class PlatformCompat extends IPlatformCompat.Stub { } @Override + @EnforcePermission(OVERRIDE_COMPAT_CHANGE_CONFIG) public void clearOverrides(String packageName) { - checkCompatChangeOverridePermission(); mCompatConfig.removePackageOverrides(packageName); killPackage(packageName); } @Override + @EnforcePermission(OVERRIDE_COMPAT_CHANGE_CONFIG) public void clearOverridesForTest(String packageName) { - checkCompatChangeOverridePermission(); mCompatConfig.removePackageOverrides(packageName); } @Override + @EnforcePermission(OVERRIDE_COMPAT_CHANGE_CONFIG) public boolean clearOverride(long changeId, String packageName) { - checkCompatChangeOverridePermission(); boolean existed = mCompatConfig.removeOverride(changeId, packageName); killPackage(packageName); return existed; } @Override + @EnforcePermission(OVERRIDE_COMPAT_CHANGE_CONFIG) public boolean clearOverrideForTest(long changeId, String packageName) { - checkCompatChangeOverridePermission(); return mCompatConfig.removeOverride(changeId, packageName); } @Override + @EnforcePermission(OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD) public void removeAllOverridesOnReleaseBuilds( CompatibilityOverridesToRemoveByPackageConfig overridesToRemoveByPackage) { - checkCompatChangeOverrideOverridablePermission(); for (CompatibilityOverridesToRemoveConfig overridesToRemove : overridesToRemoveByPackage.packageNameToOverridesToRemove.values()) { checkAllCompatOverridesAreOverridable(overridesToRemove.changeIds); @@ -303,27 +303,28 @@ public class PlatformCompat extends IPlatformCompat.Stub { } @Override + @EnforcePermission(OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD) public void removeOverridesOnReleaseBuilds( CompatibilityOverridesToRemoveConfig overridesToRemove, String packageName) { - checkCompatChangeOverrideOverridablePermission(); checkAllCompatOverridesAreOverridable(overridesToRemove.changeIds); mCompatConfig.removePackageOverrides(overridesToRemove, packageName); } @Override + @EnforcePermission(allOf = {LOG_COMPAT_CHANGE, READ_COMPAT_CHANGE_CONFIG}) public CompatibilityChangeConfig getAppConfig(ApplicationInfo appInfo) { - checkCompatChangeReadAndLogPermission(); return mCompatConfig.getAppConfig(appInfo); } @Override + @EnforcePermission(READ_COMPAT_CHANGE_CONFIG) public CompatibilityChangeInfo[] listAllChanges() { - checkCompatChangeReadPermission(); return mCompatConfig.dumpChanges(); } @Override + @RequiresNoPermission public CompatibilityChangeInfo[] listUIChanges() { return Arrays.stream(listAllChanges()).filter(this::isShownInUI).toArray( CompatibilityChangeInfo[]::new); @@ -362,11 +363,15 @@ public class PlatformCompat extends IPlatformCompat.Stub { if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, "platform_compat", pw)) { return; } - checkCompatChangeReadAndLogPermission(); + mContext.enforceCallingOrSelfPermission( + READ_COMPAT_CHANGE_CONFIG, "Cannot read compat change"); + mContext.enforceCallingOrSelfPermission( + LOG_COMPAT_CHANGE, "Cannot read log compat change usage"); mCompatConfig.dumpConfig(pw); } @Override + @RequiresNoPermission public IOverrideValidator getOverrideValidator() { return mCompatConfig.getOverrideValidator(); } @@ -414,49 +419,6 @@ public class PlatformCompat extends IPlatformCompat.Stub { } } - private void checkCompatChangeLogPermission() throws SecurityException { - // Don't check for permissions within the system process - if (Binder.getCallingUid() == SYSTEM_UID) { - return; - } - if (mContext.checkCallingOrSelfPermission(LOG_COMPAT_CHANGE) != PERMISSION_GRANTED) { - throw new SecurityException("Cannot log compat change usage"); - } - } - - private void checkCompatChangeReadPermission() { - // Don't check for permissions within the system process - if (Binder.getCallingUid() == SYSTEM_UID) { - return; - } - if (mContext.checkCallingOrSelfPermission(READ_COMPAT_CHANGE_CONFIG) - != PERMISSION_GRANTED) { - throw new SecurityException("Cannot read compat change"); - } - } - - private void checkCompatChangeOverridePermission() { - // Don't check for permissions within the system process - if (Binder.getCallingUid() == SYSTEM_UID) { - return; - } - if (mContext.checkCallingOrSelfPermission(OVERRIDE_COMPAT_CHANGE_CONFIG) - != PERMISSION_GRANTED) { - throw new SecurityException("Cannot override compat change"); - } - } - - private void checkCompatChangeOverrideOverridablePermission() { - // Don't check for permissions within the system process - if (Binder.getCallingUid() == SYSTEM_UID) { - return; - } - if (mContext.checkCallingOrSelfPermission(OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD) - != PERMISSION_GRANTED) { - throw new SecurityException("Cannot override compat change"); - } - } - private void checkAllCompatOverridesAreOverridable(Collection<Long> changeIds) { for (Long changeId : changeIds) { if (isKnownChangeId(changeId) && !mCompatConfig.isOverridable(changeId)) { @@ -466,11 +428,6 @@ public class PlatformCompat extends IPlatformCompat.Stub { } } - private void checkCompatChangeReadAndLogPermission() { - checkCompatChangeReadPermission(); - checkCompatChangeLogPermission(); - } - private boolean isShownInUI(CompatibilityChangeInfo change) { if (change.getLoggingOnly()) { return false; diff --git a/services/core/java/com/android/server/display/DisplayDeviceInfo.java b/services/core/java/com/android/server/display/DisplayDeviceInfo.java index edaa18a88637..a6613589cbc4 100644 --- a/services/core/java/com/android/server/display/DisplayDeviceInfo.java +++ b/services/core/java/com/android/server/display/DisplayDeviceInfo.java @@ -173,7 +173,7 @@ final class DisplayDeviceInfo { public static final int TOUCH_VIRTUAL = 3; /** - * Diff result: The {@link #state} fields differ. + * Diff result: The {@link #state} or {@link #committedState} fields differ. */ public static final int DIFF_STATE = 1 << 0; @@ -335,6 +335,13 @@ final class DisplayDeviceInfo { public int state = Display.STATE_ON; /** + * Display committed state. + * + * This matches {@link DisplayDeviceInfo#state} only after the power state change finishes. + */ + public int committedState = Display.STATE_UNKNOWN; + + /** * The UID of the application that owns this display, or zero if it is owned by the system. * <p> * If the display is private, then only the owner can use it. @@ -387,7 +394,7 @@ final class DisplayDeviceInfo { */ public int diff(DisplayDeviceInfo other) { int diff = 0; - if (state != other.state) { + if (state != other.state || committedState != other.committedState) { diff |= DIFF_STATE; } if (colorMode != other.colorMode) { @@ -461,6 +468,7 @@ final class DisplayDeviceInfo { address = other.address; deviceProductInfo = other.deviceProductInfo; state = other.state; + committedState = other.committedState; ownerUid = other.ownerUid; ownerPackageName = other.ownerPackageName; frameRateOverrides = other.frameRateOverrides; @@ -501,6 +509,7 @@ final class DisplayDeviceInfo { } sb.append(", deviceProductInfo ").append(deviceProductInfo); sb.append(", state ").append(Display.stateToString(state)); + sb.append(", committedState ").append(Display.stateToString(committedState)); if (ownerUid != 0 || ownerPackageName != null) { sb.append(", owner ").append(ownerPackageName); sb.append(" (uid ").append(ownerUid).append(")"); diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index 5fcdc8a08b5d..078c4309ff7f 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -243,10 +243,6 @@ public final class DisplayManagerService extends SystemService { // This option may disable certain display adapters. public boolean mSafeMode; - // True if we are in a special boot mode where only core applications and - // services should be started. This option may disable certain display adapters. - public boolean mOnlyCore; - // All callback records indexed by calling process id. public final SparseArray<CallbackRecord> mCallbacks = new SparseArray<CallbackRecord>(); @@ -622,10 +618,9 @@ public final class DisplayManagerService extends SystemService { /** * Called when the system is ready to go. */ - public void systemReady(boolean safeMode, boolean onlyCore) { + public void systemReady(boolean safeMode) { synchronized (mSyncRoot) { mSafeMode = safeMode; - mOnlyCore = onlyCore; mSystemReady = true; // Just in case the top inset changed before the system was ready. At this point, any // relevant configuration should be in place. @@ -1535,10 +1530,7 @@ public final class DisplayManagerService extends SystemService { // In safe mode, we disable non-essential display adapters to give the user // an opportunity to fix broken settings or other problems that might affect // system stability. - // In only-core mode, we disable non-essential display adapters to minimize - // the number of dependencies that are started while in this mode and to - // prevent problems that might occur due to the device being encrypted. - return !mSafeMode && !mOnlyCore; + return !mSafeMode; } private void registerDisplayAdapterLocked(DisplayAdapter adapter) { @@ -2434,7 +2426,6 @@ public final class DisplayManagerService extends SystemService { pw.println("DISPLAY MANAGER (dumpsys display)"); synchronized (mSyncRoot) { - pw.println(" mOnlyCode=" + mOnlyCore); pw.println(" mSafeMode=" + mSafeMode); pw.println(" mPendingTraversal=" + mPendingTraversal); pw.println(" mViewports=" + mViewports); diff --git a/services/core/java/com/android/server/display/HighBrightnessModeController.java b/services/core/java/com/android/server/display/HighBrightnessModeController.java index 0b9d4debd16f..f98c7dff97e3 100644 --- a/services/core/java/com/android/server/display/HighBrightnessModeController.java +++ b/services/core/java/com/android/server/display/HighBrightnessModeController.java @@ -42,8 +42,8 @@ import com.android.server.display.DisplayDeviceConfig.HighBrightnessModeData; import com.android.server.display.DisplayManagerService.Clock; import java.io.PrintWriter; +import java.util.ArrayDeque; import java.util.Iterator; -import java.util.LinkedList; /** * Controls the status of high-brightness mode for devices that support it. This class assumes that @@ -110,11 +110,11 @@ class HighBrightnessModeController { private long mRunningStartTimeMillis = -1; /** - * List of previous HBM-events ordered from most recent to least recent. + * Queue of previous HBM-events ordered from most recent to least recent. * Meant to store only the events that fall into the most recent - * {@link mHbmData.timeWindowMillis}. + * {@link HighBrightnessModeData#timeWindowMillis mHbmData.timeWindowMillis}. */ - private LinkedList<HbmEvent> mEvents = new LinkedList<>(); + private final ArrayDeque<HbmEvent> mEvents = new ArrayDeque<>(); HighBrightnessModeController(Handler handler, int width, int height, IBinder displayToken, String displayUniqueId, float brightnessMin, float brightnessMax, @@ -234,7 +234,7 @@ class HighBrightnessModeController { mRunningStartTimeMillis = -1; if (DEBUG) { - Slog.d(TAG, "New HBM event: " + mEvents.getFirst()); + Slog.d(TAG, "New HBM event: " + mEvents.peekFirst()); } } } @@ -433,7 +433,7 @@ class HighBrightnessModeController { // window by at least minTime. Basically, we're calculating the soonest time we can // get {@code timeMinMillis} back to us. final long windowstartTimeMillis = currentTime - mHbmData.timeWindowMillis; - final HbmEvent lastEvent = mEvents.getLast(); + final HbmEvent lastEvent = mEvents.peekLast(); final long startTimePlusMinMillis = Math.max(windowstartTimeMillis, lastEvent.startTimeMillis) + mHbmData.timeMinMillis; diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java index fa2f5000abbc..3ed81282665d 100644 --- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java +++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java @@ -199,6 +199,8 @@ final class LocalDisplayAdapter extends DisplayAdapter { private DisplayDeviceInfo mInfo; private boolean mHavePendingChanges; private int mState = Display.STATE_UNKNOWN; + private int mCommittedState = Display.STATE_UNKNOWN; + // This is only set in the runnable returned from requestDisplayStateLocked. private float mBrightnessState = PowerManager.BRIGHTNESS_INVALID_FLOAT; private float mSdrBrightnessState = PowerManager.BRIGHTNESS_INVALID_FLOAT; @@ -639,6 +641,7 @@ final class LocalDisplayAdapter extends DisplayAdapter { mInfo.appVsyncOffsetNanos = mActiveSfDisplayMode.appVsyncOffsetNanos; mInfo.presentationDeadlineNanos = mActiveSfDisplayMode.presentationDeadlineNanos; mInfo.state = mState; + mInfo.committedState = mCommittedState; mInfo.uniqueId = getUniqueId(); final DisplayAddress.Physical physicalAddress = DisplayAddress.fromPhysicalDisplayId(mPhysicalDisplayId); @@ -824,6 +827,7 @@ final class LocalDisplayAdapter extends DisplayAdapter { } finally { Trace.traceEnd(Trace.TRACE_TAG_POWER); } + setCommittedState(state); // If we're entering a suspended (but not OFF) power state and we // have a sidekick available, tell it now that it can take control. if (Display.isSuspendedState(state) && state != Display.STATE_OFF @@ -838,6 +842,16 @@ final class LocalDisplayAdapter extends DisplayAdapter { } } + private void setCommittedState(int state) { + // After the display state is set, let's update the committed state. + getHandler().post(() -> { + synchronized (getSyncRoot()) { + mCommittedState = state; + updateDeviceInfoLocked(); + } + }); + } + private void setDisplayBrightness(float brightnessState, float sdrBrightnessState) { // brightnessState includes invalid, off and full range. @@ -1103,6 +1117,7 @@ final class LocalDisplayAdapter extends DisplayAdapter { pw.println("mDefaultModeId=" + mDefaultModeId); pw.println("mUserPreferredModeId=" + mUserPreferredModeId); pw.println("mState=" + Display.stateToString(mState)); + pw.println("mCommittedState=" + Display.stateToString(mCommittedState)); pw.println("mBrightnessState=" + mBrightnessState); pw.println("mBacklightAdapter=" + mBacklightAdapter); pw.println("mAllmSupported=" + mAllmSupported); diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java index a640497d7e10..839555b32181 100644 --- a/services/core/java/com/android/server/display/LogicalDisplay.java +++ b/services/core/java/com/android/server/display/LogicalDisplay.java @@ -413,6 +413,7 @@ final class LogicalDisplay { mBaseDisplayInfo.appVsyncOffsetNanos = deviceInfo.appVsyncOffsetNanos; mBaseDisplayInfo.presentationDeadlineNanos = deviceInfo.presentationDeadlineNanos; mBaseDisplayInfo.state = deviceInfo.state; + mBaseDisplayInfo.committedState = deviceInfo.committedState; mBaseDisplayInfo.smallestNominalAppWidth = maskedWidth; mBaseDisplayInfo.smallestNominalAppHeight = maskedHeight; mBaseDisplayInfo.largestNominalAppWidth = maskedWidth; diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java index 576a5ff4305e..26e38bdb6d51 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java @@ -306,16 +306,23 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { @Override @ServiceThreadOnly protected void onInitializeCecComplete(int initiatedBy) { - if (initiatedBy == HdmiControlService.INITIATED_BY_SCREEN_ON) { - oneTouchPlay(new IHdmiControlCallback.Stub() { - @Override - public void onComplete(int result) { - if (result != HdmiControlManager.RESULT_SUCCESS) { - Slog.w(TAG, "Failed to complete One Touch Play. result=" + result); - } - } - }); + if (initiatedBy != HdmiControlService.INITIATED_BY_SCREEN_ON) { + return; } + @HdmiControlManager.PowerControlMode + String powerControlMode = mService.getHdmiCecConfig().getStringValue( + HdmiControlManager.CEC_SETTING_NAME_POWER_CONTROL_MODE); + if (powerControlMode.equals(HdmiControlManager.POWER_CONTROL_MODE_NONE)) { + return; + } + oneTouchPlay(new IHdmiControlCallback.Stub() { + @Override + public void onComplete(int result) { + if (result != HdmiControlManager.RESULT_SUCCESS) { + Slog.w(TAG, "Failed to complete One Touch Play. result=" + result); + } + } + }); } @Override diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java index 8ab0b931be11..3af46e3f64d1 100644 --- a/services/core/java/com/android/server/input/InputManagerService.java +++ b/services/core/java/com/android/server/input/InputManagerService.java @@ -16,6 +16,7 @@ package com.android.server.input; +import static android.provider.DeviceConfig.NAMESPACE_INPUT_NATIVE_BOOT; import static android.view.KeyEvent.KEYCODE_UNKNOWN; import android.annotation.NonNull; @@ -150,13 +151,16 @@ import java.util.OptionalInt; public class InputManagerService extends IInputManager.Stub implements Watchdog.Monitor { static final String TAG = "InputManager"; - static final boolean DEBUG = false; + // To enable these logs, run: 'adb shell setprop log.tag.InputManager DEBUG' (requires restart) + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private static final String EXCLUDED_DEVICES_PATH = "etc/excluded-input-devices.xml"; private static final String PORT_ASSOCIATIONS_PATH = "etc/input-port-associations.xml"; // Feature flag name for the deep press feature private static final String DEEP_PRESS_ENABLED = "deep_press_enabled"; + // Feature flag name for the strategy to be used in VelocityTracker + private static final String VELOCITYTRACKER_STRATEGY_PROPERTY = "velocitytracker_strategy"; private static final int MSG_DELIVER_INPUT_DEVICES_CHANGED = 1; private static final int MSG_SWITCH_KEYBOARD_LAYOUT = 2; @@ -358,6 +362,8 @@ public class InputManagerService extends IInputManager.Stub public static final int SW_CAMERA_LENS_COVER_BIT = 1 << SW_CAMERA_LENS_COVER; public static final int SW_MUTE_DEVICE_BIT = 1 << SW_MUTE_DEVICE; + private final String mVelocityTrackerStrategy; + /** Whether to use the dev/input/event or uevent subsystem for the audio jack. */ final boolean mUseDevInputEventForAudioJack; @@ -406,6 +412,8 @@ public class InputManagerService extends IInputManager.Stub mDoubleTouchGestureEnableFile = TextUtils.isEmpty(doubleTouchGestureEnablePath) ? null : new File(doubleTouchGestureEnablePath); + mVelocityTrackerStrategy = DeviceConfig.getProperty( + NAMESPACE_INPUT_NATIVE_BOOT, VELOCITYTRACKER_STRATEGY_PROPERTY); LocalServices.addService(InputManagerInternal.class, new LocalService()); } @@ -878,6 +886,11 @@ public class InputManagerService extends IInputManager.Stub return mNative.verifyInputEvent(event); } + @Override // Binder call + public String getVelocityTrackerStrategy() { + return mVelocityTrackerStrategy; + } + /** * Gets information about the input device with the specified id. * @param deviceId The device id. @@ -1004,6 +1017,10 @@ public class InputManagerService extends IInputManager.Stub final InputDevice inputDevice = mInputDevices[i]; deviceIdAndGeneration[i * 2] = inputDevice.getId(); deviceIdAndGeneration[i * 2 + 1] = inputDevice.getGeneration(); + if (DEBUG) { + Log.d(TAG, "device " + inputDevice.getId() + " generation " + + inputDevice.getGeneration()); + } if (!inputDevice.isVirtual() && inputDevice.isFullKeyboard()) { if (!containsInputDeviceWithDescriptor(oldInputDevices, @@ -1527,8 +1544,8 @@ public class InputManagerService extends IInputManager.Stub layout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor()); } if (DEBUG) { - Slog.d(TAG, "Loaded keyboard layout id for " + key + " and got " - + layout); + Slog.d(TAG, "getCurrentKeyboardLayoutForInputDevice() " + + identifier.toString() + ": " + layout); } return layout; } @@ -1550,7 +1567,9 @@ public class InputManagerService extends IInputManager.Stub try { if (mDataStore.setCurrentKeyboardLayout(key, keyboardLayoutDescriptor)) { if (DEBUG) { - Slog.d(TAG, "Saved keyboard layout using " + key); + Slog.d(TAG, "setCurrentKeyboardLayoutForInputDevice() " + identifier + + " key: " + key + + " keyboardLayoutDescriptor: " + keyboardLayoutDescriptor); } mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS); } @@ -2343,7 +2362,7 @@ public class InputManagerService extends IInputManager.Stub public void removePortAssociation(@NonNull String inputPort) { if (!checkCallingPermission( android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY, - "clearPortAssociations()")) { + "removePortAssociation()")) { throw new SecurityException( "Requires ASSOCIATE_INPUT_DEVICE_TO_DISPLAY permission"); } @@ -2359,7 +2378,7 @@ public class InputManagerService extends IInputManager.Stub public void addUniqueIdAssociation(@NonNull String inputPort, @NonNull String displayUniqueId) { if (!checkCallingPermission( android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY, - "addNameAssociation()")) { + "addUniqueIdAssociation()")) { throw new SecurityException( "Requires ASSOCIATE_INPUT_DEVICE_TO_DISPLAY permission"); } diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index ce8b9fabd5a0..05b1dd245cd3 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -4814,7 +4814,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } @BinderThread - private void hideMySoftInput(@NonNull IBinder token, int flags) { + private void hideMySoftInput(@NonNull IBinder token, int flags, + @SoftInputShowHideReason int reason) { Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.hideMySoftInput"); synchronized (ImfLock.class) { if (!calledWithValidTokenLocked(token)) { @@ -4822,10 +4823,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } final long ident = Binder.clearCallingIdentity(); try { - hideCurrentInputLocked( - mLastImeTargetWindow, flags, null, - SoftInputShowHideReason.HIDE_MY_SOFT_INPUT); - + hideCurrentInputLocked(mLastImeTargetWindow, flags, null, reason); } finally { Binder.restoreCallingIdentity(ident); } @@ -4843,7 +4841,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub final long ident = Binder.clearCallingIdentity(); try { showCurrentInputLocked(mLastImeTargetWindow, flags, null, - SoftInputShowHideReason.SHOW_MY_SOFT_INPUT); + SoftInputShowHideReason.SHOW_SOFT_INPUT_FROM_IME); } finally { Binder.restoreCallingIdentity(ident); } @@ -6651,11 +6649,12 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub @BinderThread @Override - public void hideMySoftInput(int flags, AndroidFuture future /* T=Void */) { + public void hideMySoftInput(int flags, @SoftInputShowHideReason int reason, + AndroidFuture future /* T=Void */) { @SuppressWarnings("unchecked") final AndroidFuture<Void> typedFuture = future; try { - mImms.hideMySoftInput(mToken, flags); + mImms.hideMySoftInput(mToken, flags, reason); typedFuture.complete(null); } catch (Throwable e) { typedFuture.completeExceptionally(e); diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java index e6bc79679a8f..5a40b30551b6 100644 --- a/services/core/java/com/android/server/notification/ManagedServices.java +++ b/services/core/java/com/android/server/notification/ManagedServices.java @@ -1447,6 +1447,16 @@ abstract public class ManagedServices { } } + @VisibleForTesting + void reregisterService(final ComponentName cn, final int userId) { + // If rebinding a package that died, ensure it still has permission + // after the rebind delay + if (isPackageOrComponentAllowed(cn.getPackageName(), userId) + || isPackageOrComponentAllowed(cn.flattenToString(), userId)) { + registerService(cn, userId); + } + } + /** * Inject a system service into the management list. */ @@ -1545,12 +1555,9 @@ abstract public class ManagedServices { unbindService(this, name, userid); if (!mServicesRebinding.contains(servicesBindingTag)) { mServicesRebinding.add(servicesBindingTag); - mHandler.postDelayed(new Runnable() { - @Override - public void run() { - registerService(name, userid); - } - }, ON_BINDING_DIED_REBIND_DELAY_MS); + mHandler.postDelayed(() -> + reregisterService(name, userid), + ON_BINDING_DIED_REBIND_DELAY_MS); } else { Slog.v(TAG, getCaption() + " not rebinding in user " + userid + " as a previous rebind attempt was made: " + name); diff --git a/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java b/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java index a9b2570a3dda..e09f7b09b4d1 100644 --- a/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java +++ b/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java @@ -40,11 +40,12 @@ import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.Iterator; -import java.util.LinkedList; +import java.util.List; import java.util.Set; /** @@ -76,7 +77,7 @@ public class NotificationHistoryDatabase { private final Handler mFileWriteHandler; @VisibleForTesting // List of files holding history information, sorted newest to oldest - final LinkedList<AtomicFile> mHistoryFiles; + final List<AtomicFile> mHistoryFiles; private final File mHistoryDir; private final File mVersionFile; // Current version of the database files schema @@ -94,7 +95,7 @@ public class NotificationHistoryDatabase { mFileWriteHandler = fileWriteHandler; mVersionFile = new File(dir, "version"); mHistoryDir = new File(dir, "history"); - mHistoryFiles = new LinkedList<>(); + mHistoryFiles = new ArrayList<>(); mBuffer = new NotificationHistory(); mWriteBufferRunnable = new WriteBufferRunnable(); @@ -133,7 +134,7 @@ public class NotificationHistoryDatabase { safeParseLong(lhs.getName()))); for (File file : files) { - mHistoryFiles.addLast(new AtomicFile(file)); + mHistoryFiles.add(new AtomicFile(file)); } } @@ -411,7 +412,7 @@ public class NotificationHistoryDatabase { + file.getBaseFile().getAbsolutePath()); try { writeLocked(file, mBuffer); - mHistoryFiles.addFirst(file); + mHistoryFiles.add(0, file); mBuffer = new NotificationHistory(); scheduleDeletion(file.getBaseFile(), time, HISTORY_RETENTION_DAYS); diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 21ee4c21ceeb..77c171ca35f1 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -94,6 +94,7 @@ import static android.service.notification.NotificationListenerService.REASON_ER import static android.service.notification.NotificationListenerService.REASON_GROUP_SUMMARY_CANCELED; import static android.service.notification.NotificationListenerService.REASON_LISTENER_CANCEL; import static android.service.notification.NotificationListenerService.REASON_LISTENER_CANCEL_ALL; +import static android.service.notification.NotificationListenerService.REASON_LOCKDOWN; import static android.service.notification.NotificationListenerService.REASON_PACKAGE_BANNED; import static android.service.notification.NotificationListenerService.REASON_PACKAGE_CHANGED; import static android.service.notification.NotificationListenerService.REASON_PACKAGE_SUSPENDED; @@ -252,6 +253,7 @@ import android.util.Log; import android.util.Pair; import android.util.Slog; import android.util.SparseArray; +import android.util.SparseBooleanArray; import android.util.StatsEvent; import android.util.TypedXmlPullParser; import android.util.TypedXmlSerializer; @@ -284,6 +286,7 @@ import com.android.internal.util.DumpUtils; import com.android.internal.util.Preconditions; import com.android.internal.util.XmlUtils; import com.android.internal.util.function.TriPredicate; +import com.android.internal.widget.LockPatternUtils; import com.android.server.DeviceIdleInternal; import com.android.server.EventLogTags; import com.android.server.IoThread; @@ -500,7 +503,7 @@ public class NotificationManagerService extends SystemService { private ActivityManagerInternal mAmi; private IPackageManager mPackageManager; private PackageManager mPackageManagerClient; - private PackageManagerInternal mPackageManagerInternal; + PackageManagerInternal mPackageManagerInternal; private PermissionPolicyInternal mPermissionPolicyInternal; AudioManager mAudioManager; AudioManagerInternal mAudioManagerInternal; @@ -1923,6 +1926,54 @@ public class NotificationManagerService extends SystemService { private SettingsObserver mSettingsObserver; protected ZenModeHelper mZenModeHelper; + protected class StrongAuthTracker extends LockPatternUtils.StrongAuthTracker { + + SparseBooleanArray mUserInLockDownMode = new SparseBooleanArray(); + boolean mIsInLockDownMode = false; + + StrongAuthTracker(Context context) { + super(context); + } + + private boolean containsFlag(int haystack, int needle) { + return (haystack & needle) != 0; + } + + public boolean isInLockDownMode() { + return mIsInLockDownMode; + } + + @Override + public synchronized void onStrongAuthRequiredChanged(int userId) { + boolean userInLockDownModeNext = containsFlag(getStrongAuthForUser(userId), + STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN); + mUserInLockDownMode.put(userId, userInLockDownModeNext); + boolean isInLockDownModeNext = mUserInLockDownMode.indexOfValue(true) != -1; + + if (mIsInLockDownMode == isInLockDownModeNext) { + return; + } + + if (isInLockDownModeNext) { + cancelNotificationsWhenEnterLockDownMode(); + } + + // When the mIsInLockDownMode is true, both notifyPostedLocked and + // notifyRemovedLocked will be dismissed. So we shall call + // cancelNotificationsWhenEnterLockDownMode before we set mIsInLockDownMode + // as true and call postNotificationsWhenExitLockDownMode after we set + // mIsInLockDownMode as false. + mIsInLockDownMode = isInLockDownModeNext; + + if (!isInLockDownModeNext) { + postNotificationsWhenExitLockDownMode(); + } + } + } + + private LockPatternUtils mLockPatternUtils; + private StrongAuthTracker mStrongAuthTracker; + public NotificationManagerService(Context context) { this(context, new NotificationRecordLoggerImpl(), @@ -1952,6 +2003,11 @@ public class NotificationManagerService extends SystemService { } @VisibleForTesting + void setStrongAuthTracker(StrongAuthTracker strongAuthTracker) { + mStrongAuthTracker = strongAuthTracker; + } + + @VisibleForTesting void setKeyguardManager(KeyguardManager keyguardManager) { mKeyguardManager = keyguardManager; } @@ -2145,6 +2201,8 @@ public class NotificationManagerService extends SystemService { mPlatformCompat = IPlatformCompat.Stub.asInterface( ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE)); + mLockPatternUtils = new LockPatternUtils(getContext()); + mStrongAuthTracker = new StrongAuthTracker(getContext()); mUiHandler = new Handler(UiThread.get().getLooper()); String[] extractorNames; try { @@ -2641,6 +2699,7 @@ public class NotificationManagerService extends SystemService { bubbsExtractor.setShortcutHelper(mShortcutHelper); } registerNotificationPreferencesPullers(); + mLockPatternUtils.registerStrongAuthTracker(mStrongAuthTracker); } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) { // This observer will force an update when observe is called, causing us to // bind to listener services. @@ -9537,6 +9596,29 @@ public class NotificationManagerService extends SystemService { } } + private void cancelNotificationsWhenEnterLockDownMode() { + synchronized (mNotificationLock) { + int numNotifications = mNotificationList.size(); + for (int i = 0; i < numNotifications; i++) { + NotificationRecord rec = mNotificationList.get(i); + mListeners.notifyRemovedLocked(rec, REASON_LOCKDOWN, + rec.getStats()); + } + + } + } + + private void postNotificationsWhenExitLockDownMode() { + synchronized (mNotificationLock) { + int numNotifications = mNotificationList.size(); + for (int i = 0; i < numNotifications; i++) { + NotificationRecord rec = mNotificationList.get(i); + mListeners.notifyPostedLocked(rec, rec); + } + + } + } + private void updateNotificationPulse() { synchronized (mNotificationLock) { updateLightsLocked(); @@ -9706,7 +9788,7 @@ public class NotificationManagerService extends SystemService { * notifications visible to the given listener. */ @GuardedBy("mNotificationLock") - private NotificationRankingUpdate makeRankingUpdateLocked(ManagedServiceInfo info) { + NotificationRankingUpdate makeRankingUpdateLocked(ManagedServiceInfo info) { final int N = mNotificationList.size(); final ArrayList<NotificationListenerService.Ranking> rankings = new ArrayList<>(); @@ -9753,6 +9835,10 @@ public class NotificationManagerService extends SystemService { rankings.toArray(new NotificationListenerService.Ranking[0])); } + boolean isInLockDownMode() { + return mStrongAuthTracker.isInLockDownMode(); + } + boolean hasCompanionDevice(ManagedServiceInfo info) { if (mCompanionManager == null) { mCompanionManager = getCompanionManager(); @@ -10804,8 +10890,12 @@ public class NotificationManagerService extends SystemService { * targetting <= O_MR1 */ @GuardedBy("mNotificationLock") - private void notifyPostedLocked(NotificationRecord r, NotificationRecord old, + void notifyPostedLocked(NotificationRecord r, NotificationRecord old, boolean notifyAllListeners) { + if (isInLockDownMode()) { + return; + } + try { // Lazily initialized snapshots of the notification. StatusBarNotification sbn = r.getSbn(); @@ -10813,7 +10903,7 @@ public class NotificationManagerService extends SystemService { TrimCache trimCache = new TrimCache(sbn); for (final ManagedServiceInfo info : getServices()) { - boolean sbnVisible = isVisibleToListener(sbn, r. getNotificationType(), info); + boolean sbnVisible = isVisibleToListener(sbn, r.getNotificationType(), info); boolean oldSbnVisible = (oldSbn != null) && isVisibleToListener(oldSbn, old.getNotificationType(), info); // This notification hasn't been and still isn't visible -> ignore. @@ -10843,12 +10933,17 @@ public class NotificationManagerService extends SystemService { info, oldSbnLightClone, update, null, REASON_USER_STOPPED)); continue; } - // Grant access before listener is notified final int targetUserId = (info.userid == UserHandle.USER_ALL) ? UserHandle.USER_SYSTEM : info.userid; updateUriPermissions(r, old, info.component.getPackageName(), targetUserId); + mPackageManagerInternal.grantImplicitAccess( + targetUserId, null /* intent */, + UserHandle.getAppId(info.uid), + sbn.getUid(), + false /* direct */, false /* retainOnUpdate */); + final StatusBarNotification sbnToPost = trimCache.ForListener(info); mHandler.post(() -> notifyPosted(info, sbnToPost, update)); } @@ -10903,6 +10998,10 @@ public class NotificationManagerService extends SystemService { @GuardedBy("mNotificationLock") public void notifyRemovedLocked(NotificationRecord r, int reason, NotificationStats notificationStats) { + if (isInLockDownMode()) { + return; + } + final StatusBarNotification sbn = r.getSbn(); // make a copy in case changes are made to the underlying Notification object @@ -10948,6 +11047,10 @@ public class NotificationManagerService extends SystemService { */ @GuardedBy("mNotificationLock") public void notifyRankingUpdateLocked(List<NotificationRecord> changedHiddenNotifications) { + if (isInLockDownMode()) { + return; + } + boolean isHiddenRankingUpdate = changedHiddenNotifications != null && changedHiddenNotifications.size() > 0; // TODO (b/73052211): if the ranking update changed the notification type, diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java index 9e0c97502c4f..de9102a69a2e 100644 --- a/services/core/java/com/android/server/notification/ZenModeHelper.java +++ b/services/core/java/com/android/server/notification/ZenModeHelper.java @@ -121,6 +121,7 @@ public class ZenModeHelper { protected final RingerModeDelegate mRingerModeDelegate = new RingerModeDelegate(); @VisibleForTesting protected final ZenModeConditions mConditions; + Object mConfigsLock = new Object(); @VisibleForTesting final SparseArray<ZenModeConfig> mConfigs = new SparseArray<>(); private final Metrics mMetrics = new Metrics(); private final ConditionProviders.Config mServiceConfig; @@ -153,7 +154,9 @@ public class ZenModeHelper { mDefaultConfig = readDefaultConfig(mContext.getResources()); updateDefaultAutomaticRuleNames(); mConfig = mDefaultConfig.copy(); - mConfigs.put(UserHandle.USER_SYSTEM, mConfig); + synchronized (mConfigsLock) { + mConfigs.put(UserHandle.USER_SYSTEM, mConfig); + } mConsolidatedPolicy = mConfig.toNotificationPolicy(); mSettingsObserver = new SettingsObserver(mHandler); @@ -233,7 +236,9 @@ public class ZenModeHelper { public void onUserRemoved(int user) { if (user < UserHandle.USER_SYSTEM) return; if (DEBUG) Log.d(TAG, "onUserRemoved u=" + user); - mConfigs.remove(user); + synchronized (mConfigsLock) { + mConfigs.remove(user); + } } public void onUserUnlocked(int user) { @@ -248,7 +253,12 @@ public class ZenModeHelper { if (mUser == user || user < UserHandle.USER_SYSTEM) return; mUser = user; if (DEBUG) Log.d(TAG, reason + " u=" + user); - ZenModeConfig config = mConfigs.get(user); + ZenModeConfig config = null; + synchronized (mConfigsLock) { + if (mConfigs.get(user) != null) { + config = mConfigs.get(user).copy(); + } + } if (config == null) { if (DEBUG) Log.d(TAG, reason + " generating default config for user " + user); config = mDefaultConfig.copy(); @@ -685,9 +695,11 @@ public class ZenModeHelper { pw.println(Global.zenModeToString(mZenMode)); pw.print(prefix); pw.println("mConsolidatedPolicy=" + mConsolidatedPolicy.toString()); - final int N = mConfigs.size(); - for (int i = 0; i < N; i++) { - dump(pw, prefix, "mConfigs[u=" + mConfigs.keyAt(i) + "]", mConfigs.valueAt(i)); + synchronized(mConfigsLock) { + final int N = mConfigs.size(); + for (int i = 0; i < N; i++) { + dump(pw, prefix, "mConfigs[u=" + mConfigs.keyAt(i) + "]", mConfigs.valueAt(i)); + } } pw.print(prefix); pw.print("mUser="); pw.println(mUser); synchronized (mConfig) { @@ -787,7 +799,7 @@ public class ZenModeHelper { public void writeXml(TypedXmlSerializer out, boolean forBackup, Integer version, int userId) throws IOException { - synchronized (mConfigs) { + synchronized (mConfigsLock) { final int n = mConfigs.size(); for (int i = 0; i < n; i++) { if (forBackup && mConfigs.keyAt(i) != userId) { @@ -883,14 +895,18 @@ public class ZenModeHelper { } if (config.user != mUser) { // simply store away for background users - mConfigs.put(config.user, config); + synchronized (mConfigsLock) { + mConfigs.put(config.user, config); + } if (DEBUG) Log.d(TAG, "setConfigLocked: store config for user " + config.user); return true; } // handle CPS backed conditions - danger! may modify config mConditions.evaluateConfig(config, null, false /*processSubscriptions*/); - mConfigs.put(config.user, config); + synchronized (mConfigsLock) { + mConfigs.put(config.user, config); + } if (DEBUG) Log.d(TAG, "setConfigLocked reason=" + reason, new Throwable()); ZenLog.traceConfig(reason, mConfig, config); @@ -1211,7 +1227,7 @@ public class ZenModeHelper { * Generate pulled atoms about do not disturb configurations. */ public void pullRules(List<StatsEvent> events) { - synchronized (mConfig) { + synchronized (mConfigsLock) { final int numConfigs = mConfigs.size(); for (int i = 0; i < numConfigs; i++) { final int user = mConfigs.keyAt(i); diff --git a/services/core/java/com/android/server/om/IdmapManager.java b/services/core/java/com/android/server/om/IdmapManager.java index 903d02afc307..f3cb7fb6107c 100644 --- a/services/core/java/com/android/server/om/IdmapManager.java +++ b/services/core/java/com/android/server/om/IdmapManager.java @@ -19,6 +19,7 @@ package com.android.server.om; import static com.android.server.om.OverlayManagerService.DEBUG; import static com.android.server.om.OverlayManagerService.TAG; +import android.annotation.IntDef; import android.annotation.NonNull; import android.content.om.OverlayInfo; import android.content.om.OverlayableInfo; @@ -33,6 +34,8 @@ import android.util.Slog; import com.android.server.pm.parsing.pkg.AndroidPackage; import java.io.IOException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.List; /** @@ -56,6 +59,18 @@ final class IdmapManager { VENDOR_IS_Q_OR_LATER = isQOrLater; } + static final int IDMAP_NOT_EXIST = 0; + static final int IDMAP_IS_VERIFIED = 1; + static final int IDMAP_IS_MODIFIED = 1 << 1; + + @IntDef(flag = true, prefix = { "IDMAP_" }, value = { + IDMAP_NOT_EXIST, + IDMAP_IS_VERIFIED, + IDMAP_IS_MODIFIED, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface IdmapStatus {} + private final IdmapDaemon mIdmapDaemon; private final PackageManagerHelper mPackageManager; @@ -76,8 +91,14 @@ final class IdmapManager { /** * Creates the idmap for the target/overlay combination and returns whether the idmap file was * modified. + * @return the status of the specific idmap file. It's one of the following.<ul> + * <li>{@link #IDMAP_NOT_EXIST} means the idmap file is not existed.</li> + * <li>{@link #IDMAP_IS_VERIFIED} means the idmap file is verified by Idmap2d.</li> + * <li>{@link #IDMAP_IS_MODIFIED | IDMAP_IS_VERIFIED } means the idmap file is modified and + * verified by Idmap2d.</li> + * </ul>. */ - boolean createIdmap(@NonNull final AndroidPackage targetPackage, + @IdmapStatus int createIdmap(@NonNull final AndroidPackage targetPackage, @NonNull final AndroidPackage overlayPackage, String overlayBasePath, String overlayName, int userId) { if (DEBUG) { @@ -90,14 +111,15 @@ final class IdmapManager { boolean enforce = enforceOverlayable(overlayPackage); if (mIdmapDaemon.verifyIdmap(targetPath, overlayBasePath, overlayName, policies, enforce, userId)) { - return false; + return IDMAP_IS_VERIFIED; } - return mIdmapDaemon.createIdmap(targetPath, overlayBasePath, overlayName, policies, - enforce, userId) != null; + final boolean idmapCreated = mIdmapDaemon.createIdmap(targetPath, overlayBasePath, + overlayName, policies, enforce, userId) != null; + return (idmapCreated) ? IDMAP_IS_MODIFIED | IDMAP_IS_VERIFIED : IDMAP_NOT_EXIST; } catch (Exception e) { Slog.w(TAG, "failed to generate idmap for " + targetPath + " and " + overlayBasePath, e); - return false; + return IDMAP_NOT_EXIST; } } diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java index 8ecc607603a1..4e09831305ca 100644 --- a/services/core/java/com/android/server/om/OverlayManagerService.java +++ b/services/core/java/com/android/server/om/OverlayManagerService.java @@ -1477,22 +1477,25 @@ public final class OverlayManagerService extends SystemService { targetPackageNames = pm.getTargetPackageNames(userId); } - final Map<String, OverlayPaths> pendingChanges = + final ArrayMap<String, OverlayPaths> pendingChanges = new ArrayMap<>(targetPackageNames.size()); synchronized (mLock) { final OverlayPaths frameworkOverlays = - mImpl.getEnabledOverlayPaths("android", userId); + mImpl.getEnabledOverlayPaths("android", userId, false); for (final String targetPackageName : targetPackageNames) { final OverlayPaths.Builder list = new OverlayPaths.Builder(); + list.addAll(frameworkOverlays); if (!"android".equals(targetPackageName)) { - list.addAll(frameworkOverlays); + list.addAll(mImpl.getEnabledOverlayPaths(targetPackageName, userId, true)); } - list.addAll(mImpl.getEnabledOverlayPaths(targetPackageName, userId)); pendingChanges.put(targetPackageName, list.build()); } } final HashSet<String> updatedPackages = new HashSet<>(); + final HashSet<String> invalidPackages = new HashSet<>(); + pm.setEnabledOverlayPackages(userId, pendingChanges, updatedPackages, invalidPackages); + for (final String targetPackageName : targetPackageNames) { if (DEBUG) { Slog.d(TAG, "-> Updating overlay: target=" + targetPackageName + " overlays=[" @@ -1500,11 +1503,10 @@ public final class OverlayManagerService extends SystemService { + "] userId=" + userId); } - if (!pm.setEnabledOverlayPackages( - userId, targetPackageName, pendingChanges.get(targetPackageName), - updatedPackages)) { - Slog.e(TAG, String.format("Failed to change enabled overlays for %s user %d", - targetPackageName, userId)); + if (invalidPackages.contains(targetPackageName)) { + Slog.e(TAG, TextUtils.formatSimple( + "Failed to change enabled overlays for %s user %d", targetPackageName, + userId)); } } return new ArrayList<>(updatedPackages); diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java index 38781fad76fd..dade7aa09283 100644 --- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java +++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java @@ -24,6 +24,9 @@ import static android.content.om.OverlayInfo.STATE_OVERLAY_IS_BEING_REPLACED; import static android.content.om.OverlayInfo.STATE_TARGET_IS_BEING_REPLACED; import static android.os.UserHandle.USER_SYSTEM; +import static com.android.server.om.IdmapManager.IDMAP_IS_MODIFIED; +import static com.android.server.om.IdmapManager.IDMAP_IS_VERIFIED; +import static com.android.server.om.IdmapManager.IDMAP_NOT_EXIST; import static com.android.server.om.OverlayManagerService.DEBUG; import static com.android.server.om.OverlayManagerService.TAG; @@ -741,7 +744,7 @@ final class OverlayManagerServiceImpl { } OverlayPaths getEnabledOverlayPaths(@NonNull final String targetPackageName, - final int userId) { + final int userId, boolean includeImmutableOverlays) { final List<OverlayInfo> overlays = mSettings.getOverlaysForTarget(targetPackageName, userId); final OverlayPaths.Builder paths = new OverlayPaths.Builder(); @@ -751,6 +754,9 @@ final class OverlayManagerServiceImpl { if (!oi.isEnabled()) { continue; } + if (!includeImmutableOverlays && !oi.isMutable) { + continue; + } if (oi.isFabricated()) { paths.addNonApkPath(oi.baseCodePath); } else { @@ -785,15 +791,18 @@ final class OverlayManagerServiceImpl { // Immutable RROs targeting to "android", ie framework-res.apk, are handled by native // layers. final OverlayInfo updatedOverlayInfo = mSettings.getOverlayInfo(overlay, userId); + @IdmapManager.IdmapStatus int idmapStatus = IDMAP_NOT_EXIST; if (targetPackage != null && !("android".equals(info.getTargetPackageName()) && !isPackageConfiguredMutable(overlayPackage))) { - modified |= mIdmapManager.createIdmap(targetPackage, overlayPackage, - updatedOverlayInfo.baseCodePath, overlay.getOverlayName(), userId); + idmapStatus = mIdmapManager.createIdmap(targetPackage, + overlayPackage, updatedOverlayInfo.baseCodePath, overlay.getOverlayName(), + userId); + modified |= (idmapStatus & IDMAP_IS_MODIFIED) != 0; } final @OverlayInfo.State int currentState = mSettings.getState(overlay, userId); final @OverlayInfo.State int newState = calculateNewState(updatedOverlayInfo, targetPackage, - userId, flags); + userId, flags, idmapStatus); if (currentState != newState) { if (DEBUG) { Slog.d(TAG, String.format("%s:%d: %s -> %s", @@ -808,7 +817,8 @@ final class OverlayManagerServiceImpl { } private @OverlayInfo.State int calculateNewState(@NonNull final OverlayInfo info, - @Nullable final AndroidPackage targetPackage, final int userId, final int flags) + @Nullable final AndroidPackage targetPackage, final int userId, final int flags, + @IdmapManager.IdmapStatus final int idmapStatus) throws OverlayManagerSettings.BadKeyException { if ((flags & FLAG_TARGET_IS_BEING_REPLACED) != 0) { return STATE_TARGET_IS_BEING_REPLACED; @@ -822,8 +832,10 @@ final class OverlayManagerServiceImpl { return STATE_MISSING_TARGET; } - if (!mIdmapManager.idmapExists(info)) { - return STATE_NO_IDMAP; + if ((idmapStatus & IDMAP_IS_VERIFIED) == 0) { + if (!mIdmapManager.idmapExists(info)) { + return STATE_NO_IDMAP; + } } final boolean enabled = mSettings.getEnabled(info.getOverlayIdentifier(), userId); diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java index 55bca1733d37..9e3922607dab 100644 --- a/services/core/java/com/android/server/om/OverlayManagerSettings.java +++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java @@ -178,18 +178,12 @@ final class OverlayManagerSettings { List<OverlayInfo> getOverlaysForTarget(@NonNull final String targetPackageName, final int userId) { - // Immutable RROs targeting "android" are loaded from AssetManager, and so they should be - // ignored in OverlayManagerService. final List<SettingsItem> items = selectWhereTarget(targetPackageName, userId); - items.removeIf(OverlayManagerSettings::isImmutableFrameworkOverlay); return CollectionUtils.map(items, SettingsItem::getOverlayInfo); } ArrayMap<String, List<OverlayInfo>> getOverlaysForUser(final int userId) { - // Immutable RROs targeting "android" are loaded from AssetManager, and so they should be - // ignored in OverlayManagerService. final List<SettingsItem> items = selectWhereUser(userId); - items.removeIf(OverlayManagerSettings::isImmutableFrameworkOverlay); final ArrayMap<String, List<OverlayInfo>> targetInfos = new ArrayMap<>(); for (int i = 0, n = items.size(); i < n; i++) { @@ -234,10 +228,6 @@ final class OverlayManagerSettings { return mItems.stream().mapToInt(SettingsItem::getUserId).distinct().toArray(); } - private static boolean isImmutableFrameworkOverlay(@NonNull SettingsItem item) { - return !item.isMutable() && "android".equals(item.getTargetPackageName()); - } - /** * Returns true if the settings were modified, false if they remain the same. */ diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java index a91c55fb895d..9f4ceb93a9d7 100644 --- a/services/core/java/com/android/server/pm/ApexManager.java +++ b/services/core/java/com/android/server/pm/ApexManager.java @@ -16,8 +16,6 @@ package com.android.server.pm; -import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; - import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -27,7 +25,6 @@ import android.apex.ApexSessionInfo; import android.apex.ApexSessionParams; import android.apex.CompressedApexInfoList; import android.apex.IApexService; -import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.SigningDetails; @@ -42,7 +39,6 @@ import android.sysprop.ApexProperties; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; -import android.util.PrintWriterPrinter; import android.util.Singleton; import android.util.Slog; import android.util.SparseArray; @@ -58,7 +54,6 @@ import com.android.server.pm.parsing.pkg.AndroidPackage; import com.android.server.pm.parsing.pkg.ParsedPackage; import com.android.server.pm.pkg.component.ParsedApexSystemService; import com.android.server.pm.pkg.parsing.PackageInfoWithoutStateUtils; -import com.android.server.pm.pkg.parsing.ParsingPackageUtils; import com.android.server.utils.TimingsTraceAndSlog; import com.google.android.collect.Lists; @@ -69,12 +64,10 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Collections; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; -import java.util.concurrent.ExecutorService; /** * ApexManager class handles communications with the apex service to perform operation and queries, @@ -87,8 +80,6 @@ public abstract class ApexManager { public static final int MATCH_ACTIVE_PACKAGE = 1 << 0; static final int MATCH_FACTORY_PACKAGE = 1 << 1; - private static final String VNDK_APEX_MODULE_NAME_PREFIX = "com.android.vndk."; - private static final Singleton<ApexManager> sApexManagerSingleton = new Singleton<ApexManager>() { @Override @@ -111,6 +102,17 @@ public abstract class ApexManager { return sApexManagerSingleton.get(); } + static class ScanResult { + public final ApexInfo apexInfo; + public final AndroidPackage pkg; + public final String packageName; + ScanResult(ApexInfo apexInfo, AndroidPackage pkg, String packageName) { + this.apexInfo = apexInfo; + this.pkg = pkg; + this.packageName = packageName; + } + } + /** * Minimal information about APEX mount points and the original APEX package they refer to. * @hide @@ -119,16 +121,18 @@ public abstract class ApexManager { @Nullable public final String apexModuleName; public final File apexDirectory; public final File preInstalledApexPath; + public final boolean isFactory; private ActiveApexInfo(File apexDirectory, File preInstalledApexPath) { - this(null, apexDirectory, preInstalledApexPath); + this(null, apexDirectory, preInstalledApexPath, true); } private ActiveApexInfo(@Nullable String apexModuleName, File apexDirectory, - File preInstalledApexPath) { + File preInstalledApexPath, boolean isFactory) { this.apexModuleName = apexModuleName; this.apexDirectory = apexDirectory; this.preInstalledApexPath = preInstalledApexPath; + this.isFactory = isFactory; } private ActiveApexInfo(ApexInfo apexInfo) { @@ -136,10 +140,14 @@ public abstract class ApexManager { apexInfo.moduleName, new File(Environment.getApexDirectory() + File.separator + apexInfo.moduleName), - new File(apexInfo.preinstalledModulePath)); + new File(apexInfo.preinstalledModulePath), + apexInfo.isFactory); } } + abstract ApexInfo[] getAllApexInfos(); + abstract void notifyScanResult(List<ScanResult> scanResults); + /** * Returns {@link ActiveApexInfo} records relative to all active APEX packages. * @@ -148,73 +156,6 @@ public abstract class ApexManager { public abstract List<ActiveApexInfo> getActiveApexInfos(); /** - * Called by package manager service to scan apex package files when device boots up. - * - * @param packageParser The package parser to support apex package parsing and caching parsed - * results. - * @param executorService An executor to support parallel package parsing. - */ - abstract void scanApexPackagesTraced(@NonNull PackageParser2 packageParser, - @NonNull ExecutorService executorService); - - /** - * Retrieves information about an APEX package. - * - * @param packageName the package name to look for. Note that this is the package name reported - * in the APK container manifest (i.e. AndroidManifest.xml), which might - * differ from the one reported in the APEX manifest (i.e. - * apex_manifest.json). - * @param flags the type of package to return. This may match to active packages - * and factory (pre-installed) packages. - * @return a PackageInfo object with the information about the package, or null if the package - * is not found. - */ - @Nullable - public abstract PackageInfo getPackageInfo(String packageName, @PackageInfoFlags int flags); - - /** - * Retrieves information about all active APEX packages. - * - * @return a List of PackageInfo object, each one containing information about a different - * active package. - */ - abstract List<PackageInfo> getActivePackages(); - - /** - * Retrieves information about all active pre-installed APEX packages. - * - * @return a List of PackageInfo object, each one containing information about a different - * active pre-installed package. - */ - abstract List<PackageInfo> getFactoryPackages(); - - /** - * Retrieves information about all inactive APEX packages. - * - * @return a List of PackageInfo object, each one containing information about a different - * inactive package. - */ - abstract List<PackageInfo> getInactivePackages(); - - /** - * Checks if {@code packageName} is an apex package. - * - * @param packageName package to check. - * @return {@code true} if {@code packageName} is an apex package. - */ - abstract boolean isApexPackage(String packageName); - - /** - * Whether the APEX package is pre-installed or not. - * - * @param packageInfo the package to check - * @return {@code true} if this package is pre-installed, {@code false} otherwise. - */ - public static boolean isFactory(@NonNull PackageInfo packageInfo) { - return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; - } - - /** * Returns the active apex package's name that contains the (apk) package. * * @param containedPackageName The (apk) package that might be in a apex @@ -416,9 +357,11 @@ public abstract class ApexManager { /** * Performs a non-staged install of the given {@code apexFile}. + * + * @return {@code ApeInfo} about the newly installed APEX package. */ - abstract void installPackage(File apexFile, PackageParser2 packageParser) - throws PackageManagerException; + abstract ApexInfo installPackage(File apexFile, PackageParser2 packageParser, + ApexPackageInfo apexPackageInfo) throws PackageManagerException; /** * Get a list of apex system services implemented in an apex. @@ -475,9 +418,6 @@ public abstract class ApexManager { @GuardedBy("mLock") private Map<String, String> mErrorWithApkInApex = new ArrayMap<>(); - @GuardedBy("mLock") - private List<PackageInfo> mAllPackagesCache; - /** * An APEX is a file format that delivers the apex-payload wrapped in an apk container. The * apk container has a reference name, called {@code packageName}, which is found inside the @@ -497,16 +437,6 @@ public abstract class ApexManager { private ArrayMap<String, String> mApexModuleNameToActivePackageName; /** - * Whether an APEX package is active or not. - * - * @param packageInfo the package to check - * @return {@code true} if this package is active, {@code false} otherwise. - */ - private static boolean isActive(PackageInfo packageInfo) { - return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) != 0; - } - - /** * Retrieve the service from ServiceManager. If the service is not running, it will be * started, and this function will block until it is ready. */ @@ -518,252 +448,101 @@ public abstract class ApexManager { } @Override - public List<ActiveApexInfo> getActiveApexInfos() { - final TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG + "Timing", - Trace.TRACE_TAG_PACKAGE_MANAGER); - synchronized (mLock) { - if (mActiveApexInfosCache == null) { - t.traceBegin("getActiveApexInfos_noCache"); - try { - mActiveApexInfosCache = new ArraySet<>(); - final ApexInfo[] activePackages = waitForApexService().getActivePackages(); - for (int i = 0; i < activePackages.length; i++) { - ApexInfo apexInfo = activePackages[i]; - mActiveApexInfosCache.add(new ActiveApexInfo(apexInfo)); - } - } catch (RemoteException e) { - Slog.e(TAG, "Unable to retrieve packages from apexservice", e); - } - t.traceEnd(); - } - if (mActiveApexInfosCache != null) { - return new ArrayList<>(mActiveApexInfosCache); - } else { - return Collections.emptyList(); - } - } - } - - @Override - void scanApexPackagesTraced(@NonNull PackageParser2 packageParser, - @NonNull ExecutorService executorService) { - Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanApexPackagesTraced"); + ApexInfo[] getAllApexInfos() { try { - synchronized (mLock) { - scanApexPackagesInternalLocked(packageParser, executorService); - } - } finally { - Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); - } - } - - @GuardedBy("mLock") - private void scanApexPackagesInternalLocked(PackageParser2 packageParser, - ExecutorService executorService) { - final ApexInfo[] allPkgs; - try { - mAllPackagesCache = new ArrayList<>(); - mPackageNameToApexModuleName = new ArrayMap<>(); - mApexModuleNameToActivePackageName = new ArrayMap<>(); - allPkgs = waitForApexService().getAllPackages(); + return waitForApexService().getAllPackages(); } catch (RemoteException re) { Slog.e(TAG, "Unable to retrieve packages from apexservice: " + re.toString()); throw new RuntimeException(re); } - if (allPkgs.length == 0) { - return; - } - final int flags = PackageManager.GET_META_DATA - | PackageManager.GET_SIGNING_CERTIFICATES - | PackageManager.GET_SIGNATURES; - ArrayMap<File, ApexInfo> parsingApexInfo = new ArrayMap<>(); - ParallelPackageParser parallelPackageParser = - new ParallelPackageParser(packageParser, executorService); - - for (ApexInfo ai : allPkgs) { - File apexFile = new File(ai.modulePath); - parallelPackageParser.submit(apexFile, - ParsingPackageUtils.PARSE_COLLECT_CERTIFICATES); - parsingApexInfo.put(apexFile, ai); - } - - HashSet<String> activePackagesSet = new HashSet<>(); - HashSet<String> factoryPackagesSet = new HashSet<>(); - // Process results one by one - for (int i = 0; i < parsingApexInfo.size(); i++) { - ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take(); - Throwable throwable = parseResult.throwable; - ApexInfo ai = parsingApexInfo.get(parseResult.scanFile); - - if (throwable == null) { - // Calling hideAsFinal to assign derived fields for the app info flags. - parseResult.parsedPackage.hideAsFinal(); - final PackageInfo packageInfo = PackageInfoWithoutStateUtils.generate( - parseResult.parsedPackage, ai, flags); - if (packageInfo == null) { - throw new IllegalStateException("Unable to generate package info: " - + ai.modulePath); - } - mAllPackagesCache.add(packageInfo); - for (ParsedApexSystemService service : - parseResult.parsedPackage.getApexSystemServices()) { - String minSdkVersion = service.getMinSdkVersion(); - if (minSdkVersion != null && !UnboundedSdkLevel.isAtLeast(minSdkVersion)) { - Slog.d(TAG, String.format( - "ApexSystemService %s with min_sdk_version=%s is skipped", - service.getName(), service.getMinSdkVersion())); - continue; - } - String maxSdkVersion = service.getMaxSdkVersion(); - if (maxSdkVersion != null && !UnboundedSdkLevel.isAtMost(maxSdkVersion)) { - Slog.d(TAG, String.format( - "ApexSystemService %s with max_sdk_version=%s is skipped", - service.getName(), service.getMaxSdkVersion())); - continue; - } - - if (ai.isActive) { - String name = service.getName(); - for (int j = 0; j < mApexSystemServices.size(); j++) { - ApexSystemServiceInfo info = mApexSystemServices.get(j); - if (info.getName().equals(name)) { - throw new IllegalStateException(TextUtils.formatSimple( - "Duplicate apex-system-service %s from %s, %s", name, - info.mJarPath, service.getJarPath())); - } - } - ApexSystemServiceInfo info = new ApexSystemServiceInfo( - service.getName(), service.getJarPath(), - service.getInitOrder()); - mApexSystemServices.add(info); - } - } - Collections.sort(mApexSystemServices); - mPackageNameToApexModuleName.put(packageInfo.packageName, ai.moduleName); - if (ai.isActive) { - if (activePackagesSet.contains(packageInfo.packageName)) { - throw new IllegalStateException( - "Two active packages have the same name: " - + packageInfo.packageName); - } - activePackagesSet.add(packageInfo.packageName); - if (mApexModuleNameToActivePackageName.containsKey(ai.moduleName)) { - throw new IllegalStateException( - "Two active packages have the same APEX module name: " - + ai.moduleName); - } - mApexModuleNameToActivePackageName.put( - ai.moduleName, packageInfo.packageName); - } - if (ai.isFactory) { - // Don't throw when the duplicating APEX is VNDK APEX - if (factoryPackagesSet.contains(packageInfo.packageName) - && !ai.moduleName.startsWith(VNDK_APEX_MODULE_NAME_PREFIX)) { - throw new IllegalStateException( - "Two factory packages have the same name: " - + packageInfo.packageName); - } - factoryPackagesSet.add(packageInfo.packageName); - } - } else if (throwable instanceof PackageManagerException) { - final PackageManagerException e = (PackageManagerException) throwable; - // Skip parsing non-coreApp apex file if system is in minimal boot state. - if (e.error == PackageManager.INSTALL_PARSE_FAILED_ONLY_COREAPP_ALLOWED) { - Slog.w(TAG, "Scan apex failed, not a coreApp:" + ai.modulePath); - continue; - } - throw new IllegalStateException("Unable to parse: " + ai.modulePath, throwable); - } else { - throw new IllegalStateException("Unexpected exception occurred while parsing " - + ai.modulePath, throwable); - } - } } @Override - @Nullable - public PackageInfo getPackageInfo(String packageName, @PackageInfoFlags int flags) { + void notifyScanResult(List<ScanResult> scanResults) { synchronized (mLock) { - Preconditions.checkState(mAllPackagesCache != null, - "APEX packages have not been scanned"); - boolean matchActive = (flags & MATCH_ACTIVE_PACKAGE) != 0; - boolean matchFactory = (flags & MATCH_FACTORY_PACKAGE) != 0; - for (int i = 0, size = mAllPackagesCache.size(); i < size; i++) { - final PackageInfo packageInfo = mAllPackagesCache.get(i); - if (!packageInfo.packageName.equals(packageName)) { - continue; - } - if ((matchActive && isActive(packageInfo)) - || (matchFactory && isFactory(packageInfo))) { - return packageInfo; - } - } - return null; + notifyScanResultLocked(scanResults); } } - @Override - List<PackageInfo> getActivePackages() { - synchronized (mLock) { - Preconditions.checkState(mAllPackagesCache != null, - "APEX packages have not been scanned"); - final List<PackageInfo> activePackages = new ArrayList<>(); - for (int i = 0; i < mAllPackagesCache.size(); i++) { - final PackageInfo packageInfo = mAllPackagesCache.get(i); - if (isActive(packageInfo)) { - activePackages.add(packageInfo); + @GuardedBy("mLock") + private void notifyScanResultLocked(List<ScanResult> scanResults) { + mPackageNameToApexModuleName = new ArrayMap<>(); + mApexModuleNameToActivePackageName = new ArrayMap<>(); + for (ScanResult scanResult : scanResults) { + ApexInfo ai = scanResult.apexInfo; + String packageName = scanResult.packageName; + for (ParsedApexSystemService service : + scanResult.pkg.getApexSystemServices()) { + String minSdkVersion = service.getMinSdkVersion(); + if (minSdkVersion != null && !UnboundedSdkLevel.isAtLeast(minSdkVersion)) { + Slog.d(TAG, String.format( + "ApexSystemService %s with min_sdk_version=%s is skipped", + service.getName(), service.getMinSdkVersion())); + continue; + } + String maxSdkVersion = service.getMaxSdkVersion(); + if (maxSdkVersion != null && !UnboundedSdkLevel.isAtMost(maxSdkVersion)) { + Slog.d(TAG, String.format( + "ApexSystemService %s with max_sdk_version=%s is skipped", + service.getName(), service.getMaxSdkVersion())); + continue; } - } - return activePackages; - } - } - @Override - List<PackageInfo> getFactoryPackages() { - synchronized (mLock) { - Preconditions.checkState(mAllPackagesCache != null, - "APEX packages have not been scanned"); - final List<PackageInfo> factoryPackages = new ArrayList<>(); - for (int i = 0; i < mAllPackagesCache.size(); i++) { - final PackageInfo packageInfo = mAllPackagesCache.get(i); - if (isFactory(packageInfo)) { - factoryPackages.add(packageInfo); + if (ai.isActive) { + String name = service.getName(); + for (int j = 0; j < mApexSystemServices.size(); j++) { + ApexSystemServiceInfo info = mApexSystemServices.get(j); + if (info.getName().equals(name)) { + throw new IllegalStateException(TextUtils.formatSimple( + "Duplicate apex-system-service %s from %s, %s", name, + info.mJarPath, service.getJarPath())); + } + } + ApexSystemServiceInfo info = new ApexSystemServiceInfo( + service.getName(), service.getJarPath(), + service.getInitOrder()); + mApexSystemServices.add(info); } } - return factoryPackages; - } - } - - @Override - List<PackageInfo> getInactivePackages() { - synchronized (mLock) { - Preconditions.checkState(mAllPackagesCache != null, - "APEX packages have not been scanned"); - final List<PackageInfo> inactivePackages = new ArrayList<>(); - for (int i = 0; i < mAllPackagesCache.size(); i++) { - final PackageInfo packageInfo = mAllPackagesCache.get(i); - if (!isActive(packageInfo)) { - inactivePackages.add(packageInfo); + Collections.sort(mApexSystemServices); + mPackageNameToApexModuleName.put(packageName, ai.moduleName); + if (ai.isActive) { + if (mApexModuleNameToActivePackageName.containsKey(ai.moduleName)) { + throw new IllegalStateException( + "Two active packages have the same APEX module name: " + + ai.moduleName); } + mApexModuleNameToActivePackageName.put( + ai.moduleName, packageName); } - return inactivePackages; } } @Override - boolean isApexPackage(String packageName) { - if (!isApexSupported()) return false; + public List<ActiveApexInfo> getActiveApexInfos() { + final TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG + "Timing", + Trace.TRACE_TAG_PACKAGE_MANAGER); synchronized (mLock) { - Preconditions.checkState(mAllPackagesCache != null, - "APEX packages have not been scanned"); - for (int i = 0, size = mAllPackagesCache.size(); i < size; i++) { - final PackageInfo packageInfo = mAllPackagesCache.get(i); - if (packageInfo.packageName.equals(packageName)) { - return true; + if (mActiveApexInfosCache == null) { + t.traceBegin("getActiveApexInfos_noCache"); + try { + mActiveApexInfosCache = new ArraySet<>(); + final ApexInfo[] activePackages = waitForApexService().getActivePackages(); + for (int i = 0; i < activePackages.length; i++) { + ApexInfo apexInfo = activePackages[i]; + mActiveApexInfosCache.add(new ActiveApexInfo(apexInfo)); + } + } catch (RemoteException e) { + Slog.e(TAG, "Unable to retrieve packages from apexservice", e); } + t.traceEnd(); + } + if (mActiveApexInfosCache != null) { + return new ArrayList<>(mActiveApexInfosCache); + } else { + return Collections.emptyList(); } } - return false; } @Override @@ -1119,7 +898,8 @@ public abstract class ApexManager { } @Override - void installPackage(File apexFile, PackageParser2 packageParser) + ApexInfo installPackage(File apexFile, PackageParser2 packageParser, + ApexPackageInfo apexPackageInfo) throws PackageManagerException { try { final int flags = PackageManager.GET_META_DATA @@ -1133,34 +913,15 @@ public abstract class ApexManager { throw new PackageManagerException(PackageManager.INSTALL_FAILED_INVALID_APK, "Failed to generate package info for " + apexFile.getAbsolutePath()); } - final PackageInfo existingApexPkg = getPackageInfo(newApexPkg.packageName, - MATCH_ACTIVE_PACKAGE); + final PackageInfo existingApexPkg = apexPackageInfo.getPackageInfo( + newApexPkg.packageName, MATCH_ACTIVE_PACKAGE); if (existingApexPkg == null) { Slog.w(TAG, "Attempting to install new APEX package " + newApexPkg.packageName); throw new PackageManagerException(PackageManager.INSTALL_FAILED_PACKAGE_CHANGED, "It is forbidden to install new APEX packages"); } checkApexSignature(existingApexPkg, newApexPkg); - ApexInfo apexInfo = waitForApexService().installAndActivatePackage( - apexFile.getAbsolutePath()); - final ParsedPackage parsedPackage2 = packageParser.parsePackage( - new File(apexInfo.modulePath), flags, /* useCaches= */ false); - final PackageInfo finalApexPkg = PackageInfoWithoutStateUtils.generate( - parsedPackage2, apexInfo, flags); - // Installation was successful, time to update mAllPackagesCache - synchronized (mLock) { - if (isFactory(existingApexPkg)) { - existingApexPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED; - mAllPackagesCache.add(finalApexPkg); - } else { - for (int i = 0, size = mAllPackagesCache.size(); i < size; i++) { - if (mAllPackagesCache.get(i).equals(existingApexPkg)) { - mAllPackagesCache.set(i, finalApexPkg); - break; - } - } - } - } + return waitForApexService().installAndActivatePackage(apexFile.getAbsolutePath()); } catch (RemoteException e) { throw new PackageManagerException(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, "apexservice not available"); @@ -1184,40 +945,6 @@ public abstract class ApexManager { } } - /** - * Dump information about the packages contained in a particular cache - * @param packagesCache the cache to print information about. - * @param packageName a {@link String} containing a package name, or {@code null}. If set, - * only information about that specific package will be dumped. - * @param ipw the {@link IndentingPrintWriter} object to send information to. - */ - void dumpFromPackagesCache( - List<PackageInfo> packagesCache, - @Nullable String packageName, - IndentingPrintWriter ipw) { - ipw.println(); - ipw.increaseIndent(); - for (int i = 0, size = packagesCache.size(); i < size; i++) { - final PackageInfo pi = packagesCache.get(i); - if (packageName != null && !packageName.equals(pi.packageName)) { - continue; - } - ipw.println(pi.packageName); - ipw.increaseIndent(); - ipw.println("Version: " + pi.versionCode); - ipw.println("Path: " + pi.applicationInfo.sourceDir); - ipw.println("IsActive: " + isActive(pi)); - ipw.println("IsFactory: " + isFactory(pi)); - ipw.println("ApplicationInfo: "); - ipw.increaseIndent(); - pi.applicationInfo.dump(new PrintWriterPrinter(ipw), ""); - ipw.decreaseIndent(); - ipw.decreaseIndent(); - } - ipw.decreaseIndent(); - ipw.println(); - } - @Override void dump(PrintWriter pw, @Nullable String packageName) { final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", 120); @@ -1252,18 +979,6 @@ public abstract class ApexManager { } ipw.decreaseIndent(); ipw.println(); - synchronized (mLock) { - if (mAllPackagesCache == null) { - ipw.println("APEX packages have not been scanned"); - return; - } - } - ipw.println("Active APEX packages:"); - dumpFromPackagesCache(getActivePackages(), packageName, ipw); - ipw.println("Inactive APEX packages:"); - dumpFromPackagesCache(getInactivePackages(), packageName, ipw); - ipw.println("Factory APEX packages:"); - dumpFromPackagesCache(getFactoryPackages(), packageName, ipw); } catch (RemoteException e) { ipw.println("Couldn't communicate with apexd."); } @@ -1276,6 +991,16 @@ public abstract class ApexManager { */ private static final class ApexManagerFlattenedApex extends ApexManager { @Override + ApexInfo[] getAllApexInfos() { + return null; + } + + @Override + void notifyScanResult(List<ScanResult> scanResults) { + // No-op + } + + @Override public List<ActiveApexInfo> getActiveApexInfos() { // There is no apexd running in case of flattened apex // We look up the /apex directory and identify the active APEX modules from there. @@ -1302,37 +1027,6 @@ public abstract class ApexManager { } @Override - void scanApexPackagesTraced(@NonNull PackageParser2 packageParser, - @NonNull ExecutorService executorService) { - // No-op - } - - @Override - public PackageInfo getPackageInfo(String packageName, int flags) { - return null; - } - - @Override - List<PackageInfo> getActivePackages() { - return Collections.emptyList(); - } - - @Override - List<PackageInfo> getFactoryPackages() { - return Collections.emptyList(); - } - - @Override - List<PackageInfo> getInactivePackages() { - return Collections.emptyList(); - } - - @Override - boolean isApexPackage(String packageName) { - return false; - } - - @Override @Nullable public String getActiveApexPackageNameContainingPackage( @NonNull String containedPackageName) { @@ -1467,7 +1161,8 @@ public abstract class ApexManager { } @Override - void installPackage(File apexFile, PackageParser2 packageParser) { + ApexInfo installPackage(File apexFile, PackageParser2 packageParser, + ApexPackageInfo apexPackageInfo) { throw new UnsupportedOperationException("APEX updates are not supported"); } diff --git a/services/core/java/com/android/server/pm/ApexPackageInfo.java b/services/core/java/com/android/server/pm/ApexPackageInfo.java new file mode 100644 index 000000000000..21cd01c17662 --- /dev/null +++ b/services/core/java/com/android/server/pm/ApexPackageInfo.java @@ -0,0 +1,403 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.pm; + +import static com.android.server.pm.ApexManager.MATCH_ACTIVE_PACKAGE; +import static com.android.server.pm.ApexManager.MATCH_FACTORY_PACKAGE; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.apex.ApexInfo; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.util.ArrayMap; +import android.util.PrintWriterPrinter; +import android.util.Slog; + +import com.android.internal.annotations.GuardedBy; +import com.android.internal.util.IndentingPrintWriter; +import com.android.internal.util.Preconditions; +import com.android.server.pm.parsing.PackageParser2; +import com.android.server.pm.parsing.pkg.AndroidPackage; +import com.android.server.pm.parsing.pkg.ParsedPackage; +import com.android.server.pm.pkg.parsing.PackageInfoWithoutStateUtils; +import com.android.server.pm.pkg.parsing.ParsingPackageUtils; + +import java.io.File; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.concurrent.ExecutorService; + +/** + * A temporary holder to store PackageInfo for scanned apex packages. We will unify the scan/install + * flows of APK and APEX and PMS will be the only source of truth for all package information + * including both APK and APEX. This class will no longer be needed when the migration is done. + */ +class ApexPackageInfo { + public static final boolean ENABLE_FEATURE_SCAN_APEX = true; + + private static final String TAG = "ApexManager"; + private static final String VNDK_APEX_MODULE_NAME_PREFIX = "com.android.vndk."; + + private final Object mLock = new Object(); + + @GuardedBy("mLock") + private List<PackageInfo> mAllPackagesCache; + + /** + * Whether an APEX package is active or not. + * + * @param packageInfo the package to check + * @return {@code true} if this package is active, {@code false} otherwise. + */ + private static boolean isActive(PackageInfo packageInfo) { + return packageInfo.isActiveApex; + } + + /** + * Called by package manager service to scan apex package files when device boots up. + * + * @param allPackages All apex packages to scan. + * @param packageParser The package parser to support apex package parsing and caching parsed + * results. + * @param executorService An executor to support parallel package parsing. + */ + List<ApexManager.ScanResult> scanApexPackages(ApexInfo[] allPackages, + @NonNull PackageParser2 packageParser, @NonNull ExecutorService executorService) { + synchronized (mLock) { + return scanApexPackagesInternalLocked(allPackages, packageParser, executorService); + } + } + + void notifyScanResult(List<ApexManager.ScanResult> scanResults) { + synchronized (mLock) { + notifyScanResultLocked(scanResults); + } + } + + /** + * Retrieves information about an APEX package. + * + * @param packageName the package name to look for. Note that this is the package name reported + * in the APK container manifest (i.e. AndroidManifest.xml), which might + * differ from the one reported in the APEX manifest (i.e. + * apex_manifest.json). + * @param flags the type of package to return. This may match to active packages + * and factory (pre-installed) packages. + * @return a PackageInfo object with the information about the package, or null if the package + * is not found. + */ + @Nullable + PackageInfo getPackageInfo(String packageName, @ApexManager.PackageInfoFlags int flags) { + synchronized (mLock) { + Preconditions.checkState(mAllPackagesCache != null, + "APEX packages have not been scanned"); + boolean matchActive = (flags & MATCH_ACTIVE_PACKAGE) != 0; + boolean matchFactory = (flags & MATCH_FACTORY_PACKAGE) != 0; + for (int i = 0, size = mAllPackagesCache.size(); i < size; i++) { + final PackageInfo packageInfo = mAllPackagesCache.get(i); + if (!packageInfo.packageName.equals(packageName)) { + continue; + } + if ((matchActive && isActive(packageInfo)) + || (matchFactory && isFactory(packageInfo))) { + return packageInfo; + } + } + return null; + } + } + + /** + * Retrieves information about all active APEX packages. + * + * @return a List of PackageInfo object, each one containing information about a different + * active package. + */ + List<PackageInfo> getActivePackages() { + synchronized (mLock) { + Preconditions.checkState(mAllPackagesCache != null, + "APEX packages have not been scanned"); + final List<PackageInfo> activePackages = new ArrayList<>(); + for (int i = 0; i < mAllPackagesCache.size(); i++) { + final PackageInfo packageInfo = mAllPackagesCache.get(i); + if (isActive(packageInfo)) { + activePackages.add(packageInfo); + } + } + return activePackages; + } + } + + /** + * Retrieves information about all active pre-installed APEX packages. + * + * @return a List of PackageInfo object, each one containing information about a different + * active pre-installed package. + */ + List<PackageInfo> getFactoryPackages() { + synchronized (mLock) { + Preconditions.checkState(mAllPackagesCache != null, + "APEX packages have not been scanned"); + final List<PackageInfo> factoryPackages = new ArrayList<>(); + for (int i = 0; i < mAllPackagesCache.size(); i++) { + final PackageInfo packageInfo = mAllPackagesCache.get(i); + if (isFactory(packageInfo)) { + factoryPackages.add(packageInfo); + } + } + return factoryPackages; + } + } + + /** + * Retrieves information about all inactive APEX packages. + * + * @return a List of PackageInfo object, each one containing information about a different + * inactive package. + */ + List<PackageInfo> getInactivePackages() { + synchronized (mLock) { + Preconditions.checkState(mAllPackagesCache != null, + "APEX packages have not been scanned"); + final List<PackageInfo> inactivePackages = new ArrayList<>(); + for (int i = 0; i < mAllPackagesCache.size(); i++) { + final PackageInfo packageInfo = mAllPackagesCache.get(i); + if (!isActive(packageInfo)) { + inactivePackages.add(packageInfo); + } + } + return inactivePackages; + } + } + + /** + * Checks if {@code packageName} is an apex package. + * + * @param packageName package to check. + * @return {@code true} if {@code packageName} is an apex package. + */ + boolean isApexPackage(String packageName) { + synchronized (mLock) { + Preconditions.checkState(mAllPackagesCache != null, + "APEX packages have not been scanned"); + for (int i = 0, size = mAllPackagesCache.size(); i < size; i++) { + final PackageInfo packageInfo = mAllPackagesCache.get(i); + if (packageInfo.packageName.equals(packageName)) { + return true; + } + } + } + return false; + } + + /** + * Called to update cached PackageInfo when installing rebootless APEX. + */ + void notifyPackageInstalled(ApexInfo apexInfo, PackageParser2 packageParser) + throws PackageManagerException { + final int flags = PackageManager.GET_META_DATA + | PackageManager.GET_SIGNING_CERTIFICATES + | PackageManager.GET_SIGNATURES; + final ParsedPackage parsedPackage = packageParser.parsePackage( + new File(apexInfo.modulePath), flags, /* useCaches= */ false); + notifyPackageInstalled(apexInfo, parsedPackage.hideAsFinal()); + } + + void notifyPackageInstalled(ApexInfo apexInfo, AndroidPackage pkg) { + final int flags = PackageManager.GET_META_DATA + | PackageManager.GET_SIGNING_CERTIFICATES + | PackageManager.GET_SIGNATURES; + final PackageInfo newApexPkg = PackageInfoWithoutStateUtils.generate( + pkg, apexInfo, flags); + final String packageName = newApexPkg.packageName; + synchronized (mLock) { + for (int i = 0, size = mAllPackagesCache.size(); i < size; i++) { + PackageInfo oldApexPkg = mAllPackagesCache.get(i); + if (oldApexPkg.isActiveApex && oldApexPkg.packageName.equals(packageName)) { + if (isFactory(oldApexPkg)) { + oldApexPkg.isActiveApex = false; + mAllPackagesCache.add(newApexPkg); + } else { + mAllPackagesCache.set(i, newApexPkg); + } + break; + } + } + } + } + + /** + * Whether the APEX package is pre-installed or not. + * + * @param packageInfo the package to check + * @return {@code true} if this package is pre-installed, {@code false} otherwise. + */ + private static boolean isFactory(@NonNull PackageInfo packageInfo) { + return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) == 0; + } + + /** + * Dumps various state information to the provided {@link PrintWriter} object. + * + * @param pw the {@link PrintWriter} object to send information to. + * @param packageName a {@link String} containing a package name, or {@code null}. If set, only + * information about that specific package will be dumped. + */ + void dump(PrintWriter pw, @Nullable String packageName) { + final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", 120); + synchronized (mLock) { + if (mAllPackagesCache == null) { + ipw.println("APEX packages have not been scanned"); + return; + } + } + ipw.println("Active APEX packages:"); + dumpFromPackagesCache(getActivePackages(), packageName, ipw); + ipw.println("Inactive APEX packages:"); + dumpFromPackagesCache(getInactivePackages(), packageName, ipw); + ipw.println("Factory APEX packages:"); + dumpFromPackagesCache(getFactoryPackages(), packageName, ipw); + } + + @GuardedBy("mLock") + private void notifyScanResultLocked(List<ApexManager.ScanResult> scanResults) { + mAllPackagesCache = new ArrayList<>(); + final int flags = PackageManager.GET_META_DATA + | PackageManager.GET_SIGNING_CERTIFICATES + | PackageManager.GET_SIGNATURES; + + HashSet<String> activePackagesSet = new HashSet<>(); + HashSet<String> factoryPackagesSet = new HashSet<>(); + for (ApexManager.ScanResult result : scanResults) { + ApexInfo ai = result.apexInfo; + + final PackageInfo packageInfo = PackageInfoWithoutStateUtils.generate( + result.pkg, ai, flags); + if (packageInfo == null) { + throw new IllegalStateException("Unable to generate package info: " + + ai.modulePath); + } + if (!packageInfo.packageName.equals(result.packageName)) { + throw new IllegalStateException("Unmatched package name: " + + result.packageName + " != " + packageInfo.packageName + + ", path=" + ai.modulePath); + } + mAllPackagesCache.add(packageInfo); + if (ai.isActive) { + if (!activePackagesSet.add(packageInfo.packageName)) { + throw new IllegalStateException( + "Two active packages have the same name: " + + packageInfo.packageName); + } + } + if (ai.isFactory) { + // Don't throw when the duplicating APEX is VNDK APEX + if (!factoryPackagesSet.add(packageInfo.packageName) + && !ai.moduleName.startsWith(VNDK_APEX_MODULE_NAME_PREFIX)) { + throw new IllegalStateException( + "Two factory packages have the same name: " + + packageInfo.packageName); + } + } + } + } + + @GuardedBy("mLock") + private List<ApexManager.ScanResult> scanApexPackagesInternalLocked(final ApexInfo[] allPkgs, + PackageParser2 packageParser, ExecutorService executorService) { + if (allPkgs == null || allPkgs.length == 0) { + notifyScanResultLocked(Collections.EMPTY_LIST); + return Collections.EMPTY_LIST; + } + + ArrayMap<File, ApexInfo> parsingApexInfo = new ArrayMap<>(); + ParallelPackageParser parallelPackageParser = + new ParallelPackageParser(packageParser, executorService); + for (ApexInfo ai : allPkgs) { + File apexFile = new File(ai.modulePath); + parallelPackageParser.submit(apexFile, + ParsingPackageUtils.PARSE_COLLECT_CERTIFICATES); + parsingApexInfo.put(apexFile, ai); + } + + List<ApexManager.ScanResult> results = new ArrayList<>(parsingApexInfo.size()); + // Process results one by one + for (int i = 0; i < parsingApexInfo.size(); i++) { + ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take(); + Throwable throwable = parseResult.throwable; + ApexInfo ai = parsingApexInfo.get(parseResult.scanFile); + + if (throwable == null) { + // Calling hideAsFinal to assign derived fields for the app info flags. + parseResult.parsedPackage.hideAsFinal(); + results.add(new ApexManager.ScanResult( + ai, parseResult.parsedPackage, parseResult.parsedPackage.getPackageName())); + } else if (throwable instanceof PackageManagerException) { + final PackageManagerException e = (PackageManagerException) throwable; + // Skip parsing non-coreApp apex file if system is in minimal boot state. + if (e.error == PackageManager.INSTALL_PARSE_FAILED_ONLY_COREAPP_ALLOWED) { + Slog.w(TAG, "Scan apex failed, not a coreApp:" + ai.modulePath); + continue; + } + throw new IllegalStateException("Unable to parse: " + ai.modulePath, throwable); + } else { + throw new IllegalStateException("Unexpected exception occurred while parsing " + + ai.modulePath, throwable); + } + } + + notifyScanResultLocked(results); + return results; + } + + /** + * Dump information about the packages contained in a particular cache + * @param packagesCache the cache to print information about. + * @param packageName a {@link String} containing a package name, or {@code null}. If set, + * only information about that specific package will be dumped. + * @param ipw the {@link IndentingPrintWriter} object to send information to. + */ + private static void dumpFromPackagesCache(List<PackageInfo> packagesCache, + @Nullable String packageName, IndentingPrintWriter ipw) { + ipw.println(); + ipw.increaseIndent(); + for (int i = 0, size = packagesCache.size(); i < size; i++) { + final PackageInfo pi = packagesCache.get(i); + if (packageName != null && !packageName.equals(pi.packageName)) { + continue; + } + ipw.println(pi.packageName); + ipw.increaseIndent(); + ipw.println("Version: " + pi.versionCode); + ipw.println("Path: " + pi.applicationInfo.sourceDir); + ipw.println("IsActive: " + isActive(pi)); + ipw.println("IsFactory: " + isFactory(pi)); + ipw.println("ApplicationInfo: "); + ipw.increaseIndent(); + pi.applicationInfo.dump(new PrintWriterPrinter(ipw), ""); + ipw.decreaseIndent(); + ipw.decreaseIndent(); + } + ipw.decreaseIndent(); + ipw.println(); + } +} diff --git a/services/core/java/com/android/server/pm/Computer.java b/services/core/java/com/android/server/pm/Computer.java index c259797942a7..4ab58b7947e2 100644 --- a/services/core/java/com/android/server/pm/Computer.java +++ b/services/core/java/com/android/server/pm/Computer.java @@ -217,11 +217,16 @@ public interface Computer extends PackageDataSnapshot { boolean isSameProfileGroup(@UserIdInt int callerUserId, @UserIdInt int userId); boolean shouldFilterApplication(@Nullable PackageStateInternal ps, int callingUid, @Nullable ComponentName component, @PackageManager.ComponentType int componentType, + int userId, boolean filterUninstall); + boolean shouldFilterApplication(@Nullable PackageStateInternal ps, int callingUid, + @Nullable ComponentName component, @PackageManager.ComponentType int componentType, int userId); boolean shouldFilterApplication(@Nullable PackageStateInternal ps, int callingUid, int userId); boolean shouldFilterApplication(@NonNull SharedUserSetting sus, int callingUid, int userId); + boolean shouldFilterApplicationIncludingUninstalled(@Nullable PackageStateInternal ps, + int callingUid, int userId); int checkUidPermission(String permName, int uid); int getPackageUidInternal(String packageName, long flags, int userId, int callingUid); long updateFlagsForApplication(long flags, int userId); @@ -440,10 +445,6 @@ public interface Computer extends PackageDataSnapshot { boolean getBlockUninstallForUser(@NonNull String packageName, @UserIdInt int userId); @Nullable - SparseArray<int[]> getBroadcastAllowList(@NonNull String packageName, @UserIdInt int[] userIds, - boolean isInstantApp); - - @Nullable String getInstallerPackageName(@NonNull String packageName); @Nullable @@ -479,6 +480,16 @@ public interface Computer extends PackageDataSnapshot { boolean isPackageSignedByKeySetExactly(@NonNull String packageName, @NonNull KeySet ks); + /** + * See {@link AppsFilterSnapshot#getVisibilityAllowList(PackageStateInternal, int[], ArrayMap)} + */ + @Nullable + SparseArray<int[]> getVisibilityAllowLists(@NonNull String packageName, + @UserIdInt int[] userIds); + + /** + * See {@link AppsFilterSnapshot#getVisibilityAllowList(PackageStateInternal, int[], ArrayMap)} + */ @Nullable int[] getVisibilityAllowList(@NonNull String packageName, @UserIdInt int userId); diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java index 80d61b593fd2..cbabcf236fb9 100644 --- a/services/core/java/com/android/server/pm/ComputerEngine.java +++ b/services/core/java/com/android/server/pm/ComputerEngine.java @@ -397,6 +397,7 @@ public class ComputerEngine implements Computer { private final UserManagerService mUserManager; private final PermissionManagerServiceInternal mPermissionManager; private final ApexManager mApexManager; + private final ApexPackageInfo mApexPackageInfo; private final PackageManagerServiceInjector mInjector; private final ComponentResolverApi mComponentResolver; private final InstantAppResolverConnection mInstantAppResolverConnection; @@ -450,6 +451,7 @@ public class ComputerEngine implements Computer { mContext = args.service.mContext; mInjector = args.service.mInjector; mApexManager = args.service.mApexManager; + mApexPackageInfo = args.service.mApexPackageInfo; mInstantAppResolverConnection = args.service.mInstantAppResolverConnection; mDefaultAppProvider = args.service.getDefaultAppProvider(); mDomainVerificationManager = args.service.mDomainVerificationManager; @@ -540,8 +542,13 @@ public class ComputerEngine implements Computer { && ((!matchInstantApp && !isCallerInstantApp && isTargetInstantApp) || (matchVisibleToInstantAppOnly && isCallerInstantApp && isTargetHiddenFromInstantApp)); + final boolean resolveForStartNonExported = resolveForStart + && !ai.exported + && !isCallerSameApp(pkgName, filterCallingUid); final boolean blockNormalResolution = - !resolveForStart && !isTargetInstantApp && !isCallerInstantApp + (!resolveForStart || resolveForStartNonExported) + && !isTargetInstantApp + && !isCallerInstantApp && shouldFilterApplication( getPackageStateInternal(ai.applicationInfo.packageName, Process.SYSTEM_UID), filterCallingUid, userId); @@ -994,7 +1001,7 @@ public class ComputerEngine implements Computer { if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) { apexFlags = ApexManager.MATCH_FACTORY_PACKAGE; } - final PackageInfo pi = mApexManager.getPackageInfo(packageName, apexFlags); + final PackageInfo pi = mApexPackageInfo.getPackageInfo(packageName, apexFlags); if (pi == null) { return null; } @@ -1691,7 +1698,7 @@ public class ComputerEngine implements Computer { if (matchFactoryOnly) { // Instant app filtering for APEX modules is ignored if ((flags & MATCH_APEX) != 0) { - return mApexManager.getPackageInfo(packageName, + return mApexPackageInfo.getPackageInfo(packageName, ApexManager.MATCH_FACTORY_PACKAGE); } final PackageStateInternal ps = mSettings.getDisabledSystemPkg(packageName); @@ -1736,7 +1743,7 @@ public class ComputerEngine implements Computer { return generatePackageInfo(ps, flags, userId); } if ((flags & MATCH_APEX) != 0) { - return mApexManager.getPackageInfo(packageName, ApexManager.MATCH_ACTIVE_PACKAGE); + return mApexPackageInfo.getPackageInfo(packageName, ApexManager.MATCH_ACTIVE_PACKAGE); } return null; } @@ -1832,12 +1839,9 @@ public class ComputerEngine implements Computer { } if (listApex) { if (listFactory) { - list.addAll(mApexManager.getFactoryPackages()); + list.addAll(mApexPackageInfo.getFactoryPackages()); } else { - list.addAll(mApexManager.getActivePackages()); - if (listUninstalled) { - list.addAll(mApexManager.getInactivePackages()); - } + list.addAll(mApexPackageInfo.getActivePackages()); } } return new ParceledListSlice<>(list); @@ -2673,7 +2677,7 @@ public class ComputerEngine implements Computer { */ public final boolean shouldFilterApplication(@Nullable PackageStateInternal ps, int callingUid, @Nullable ComponentName component, - @PackageManager.ComponentType int componentType, int userId) { + @PackageManager.ComponentType int componentType, int userId, boolean filterUninstall) { if (Process.isSdkSandboxUid(callingUid)) { int clientAppUid = Process.getAppUidForSdkSandboxUid(callingUid); // SDK sandbox should be able to see it's client app @@ -2687,9 +2691,11 @@ public class ComputerEngine implements Computer { } final String instantAppPkgName = getInstantAppPackageName(callingUid); final boolean callerIsInstantApp = instantAppPkgName != null; - if (ps == null) { - // pretend the application exists, but, needs to be filtered - return callerIsInstantApp; + if (ps == null + || (filterUninstall && !ps.getUserStateOrDefault(userId).isInstalled())) { + // If caller is instant app and ps is null, pretend the application exists, + // but, needs to be filtered + return (callerIsInstantApp || filterUninstall); } // if the target and caller are the same application, don't filter if (isCallerSameApp(ps.getPackageName(), callingUid)) { @@ -2734,15 +2740,26 @@ public class ComputerEngine implements Computer { } /** - * @see #shouldFilterApplication(PackageStateInternal, int, ComponentName, int, int) + * @see #shouldFilterApplication(PackageStateInternal, int, ComponentName, int, int, boolean) + */ + public final boolean shouldFilterApplication(@Nullable PackageStateInternal ps, + int callingUid, @Nullable ComponentName component, + @PackageManager.ComponentType int componentType, int userId) { + return shouldFilterApplication( + ps, callingUid, component, componentType, userId, false /* filterUninstall */); + } + + /** + * @see #shouldFilterApplication(PackageStateInternal, int, ComponentName, int, int, boolean) */ public final boolean shouldFilterApplication( @Nullable PackageStateInternal ps, int callingUid, int userId) { - return shouldFilterApplication(ps, callingUid, null, TYPE_UNKNOWN, userId); + return shouldFilterApplication( + ps, callingUid, null, TYPE_UNKNOWN, userId, false /* filterUninstall */); } /** - * @see #shouldFilterApplication(PackageStateInternal, int, ComponentName, int, int) + * @see #shouldFilterApplication(PackageStateInternal, int, ComponentName, int, int, boolean) */ public final boolean shouldFilterApplication(@NonNull SharedUserSetting sus, int callingUid, int userId) { @@ -2750,13 +2767,22 @@ public class ComputerEngine implements Computer { final ArraySet<PackageStateInternal> packageStates = (ArraySet<PackageStateInternal>) sus.getPackageStates(); for (int index = packageStates.size() - 1; index >= 0 && filterApp; index--) { - filterApp &= shouldFilterApplication(packageStates.valueAt(index), - callingUid, /* component */ null, TYPE_UNKNOWN, userId); + filterApp &= shouldFilterApplication(packageStates.valueAt(index), callingUid, + null /* component */, TYPE_UNKNOWN, userId, false /* filterUninstall */); } return filterApp; } /** + * @see #shouldFilterApplication(PackageStateInternal, int, ComponentName, int, int, boolean) + */ + public final boolean shouldFilterApplicationIncludingUninstalled( + @Nullable PackageStateInternal ps, int callingUid, int userId) { + return shouldFilterApplication( + ps, callingUid, null, TYPE_UNKNOWN, userId, true /* filterUninstall */); + } + + /** * Verification statuses are ordered from the worse to the best, except for * INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER, which is the worse. */ @@ -3742,7 +3768,7 @@ public class ComputerEngine implements Computer { if (ps == null || ps.getPkg() == null) { return -1; } - if (shouldFilterApplication(ps, Binder.getCallingUid(), + if (shouldFilterApplicationIncludingUninstalled(ps, Binder.getCallingUid(), UserHandle.getCallingUserId())) { return -1; } @@ -4189,8 +4215,8 @@ public class ComputerEngine implements Computer { } final int callingUid = Binder.getCallingUid(); final int callingUserId = UserHandle.getUserId(callingUid); - if (shouldFilterApplication(ps1, callingUid, callingUserId) - || shouldFilterApplication(ps2, callingUid, callingUserId)) { + if (shouldFilterApplicationIncludingUninstalled(ps1, callingUid, callingUserId) + || shouldFilterApplicationIncludingUninstalled(ps2, callingUid, callingUserId)) { return PackageManager.SIGNATURE_UNKNOWN_PACKAGE; } return checkSignaturesInternal(p1.getSigningDetails(), p2.getSigningDetails()); @@ -4345,11 +4371,8 @@ public class ComputerEngine implements Computer { @Override public List<String> getAllPackages() { - // Allow iorapd to call this method. - if (Binder.getCallingUid() != Process.IORAPD_UID) { - PackageManagerServiceUtils.enforceSystemOrRootOrShell( - "getAllPackages is limited to privileged callers"); - } + PackageManagerServiceUtils.enforceSystemOrRootOrShell( + "getAllPackages is limited to privileged callers"); final int callingUid = Binder.getCallingUid(); final int callingUserId = UserHandle.getUserId(callingUid); if (canViewInstantApps(callingUid, callingUserId)) { @@ -4969,7 +4992,7 @@ public class ComputerEngine implements Computer { enforceCrossUserPermission(callingUid, userId, true /* requireFullPermission */, false /* checkShell */, "isPackageSuspendedForUser for user " + userId); final PackageStateInternal ps = mSettings.getPackage(packageName); - if (ps == null || shouldFilterApplication(ps, callingUid, userId)) { + if (ps == null || shouldFilterApplicationIncludingUninstalled(ps, callingUid, userId)) { throw new IllegalArgumentException("Unknown target package: " + packageName); } return ps.getUserStateOrDefault(userId).isSuspended(); @@ -5001,7 +5024,7 @@ public class ComputerEngine implements Computer { if (pkg == null || ArrayUtils.isEmpty(pkg.getActivities())) { return ParceledListSlice.emptyList(); } - if (shouldFilterApplication(ps, callingUid, callingUserId)) { + if (shouldFilterApplicationIncludingUninstalled(ps, callingUid, callingUserId)) { return ParceledListSlice.emptyList(); } final int count = ArrayUtils.size(pkg.getActivities()); @@ -5027,20 +5050,6 @@ public class ComputerEngine implements Computer { @Nullable @Override - public SparseArray<int[]> getBroadcastAllowList(@NonNull String packageName, - @UserIdInt int[] userIds, boolean isInstantApp) { - if (isInstantApp) { - return null; - } - PackageStateInternal setting = getPackageStateInternal(packageName, Process.SYSTEM_UID); - if (setting == null) { - return null; - } - return mAppsFilter.getVisibilityAllowList(setting, userIds, getPackageStates()); - } - - @Nullable - @Override public String getInstallerPackageName(@NonNull String packageName) { final int callingUid = Binder.getCallingUid(); final InstallSource installSource = getInstallSource(packageName, callingUid); @@ -5050,7 +5059,7 @@ public class ComputerEngine implements Computer { String installerPackageName = installSource.installerPackageName; if (installerPackageName != null) { final PackageStateInternal ps = mSettings.getPackage(installerPackageName); - if (ps == null || shouldFilterApplication(ps, callingUid, + if (ps == null || shouldFilterApplicationIncludingUninstalled(ps, callingUid, UserHandle.getUserId(callingUid))) { installerPackageName = null; } @@ -5063,12 +5072,12 @@ public class ComputerEngine implements Computer { final PackageStateInternal ps = mSettings.getPackage(packageName); // Installer info for Apex is not stored in PackageManager - if (ps == null && mApexManager.isApexPackage(packageName)) { + if (ps == null && mApexPackageInfo.isApexPackage(packageName)) { return InstallSource.EMPTY; } - if (ps == null - || shouldFilterApplication(ps, callingUid, UserHandle.getUserId(callingUid))) { + if (ps == null || shouldFilterApplicationIncludingUninstalled( + ps, callingUid, UserHandle.getUserId(callingUid))) { return null; } @@ -5093,7 +5102,8 @@ public class ComputerEngine implements Computer { installerPackageName = installSource.installerPackageName; if (installerPackageName != null) { final PackageStateInternal ps = mSettings.getPackage(installerPackageName); - if (ps == null || shouldFilterApplication(ps, callingUid, userId)) { + if (ps == null + || shouldFilterApplicationIncludingUninstalled(ps, callingUid, userId)) { installerPackageName = null; } } @@ -5118,7 +5128,8 @@ public class ComputerEngine implements Computer { } else { initiatingPackageName = installSource.initiatingPackageName; final PackageStateInternal ps = mSettings.getPackage(initiatingPackageName); - if (ps == null || shouldFilterApplication(ps, callingUid, userId)) { + if (ps == null + || shouldFilterApplicationIncludingUninstalled(ps, callingUid, userId)) { initiatingPackageName = null; } } @@ -5127,7 +5138,8 @@ public class ComputerEngine implements Computer { originatingPackageName = installSource.originatingPackageName; if (originatingPackageName != null) { final PackageStateInternal ps = mSettings.getPackage(originatingPackageName); - if (ps == null || shouldFilterApplication(ps, callingUid, userId)) { + if (ps == null + || shouldFilterApplicationIncludingUninstalled(ps, callingUid, userId)) { originatingPackageName = null; } } @@ -5232,10 +5244,11 @@ public class ComputerEngine implements Computer { if (packageName == null || alias == null) { return null; } + final int callingUid = Binder.getCallingUid(); + final int callingUserId = UserHandle.getUserId(callingUid); final AndroidPackage pkg = mPackages.get(packageName); - if (pkg == null - || shouldFilterApplication(getPackageStateInternal(pkg.getPackageName()), - Binder.getCallingUid(), UserHandle.getCallingUserId())) { + if (pkg == null || shouldFilterApplicationIncludingUninstalled( + getPackageStateInternal(pkg.getPackageName()), callingUid, callingUserId)) { Slog.w(TAG, "KeySet requested for unknown package: " + packageName); throw new IllegalArgumentException("Unknown package: " + packageName); } @@ -5252,9 +5265,8 @@ public class ComputerEngine implements Computer { final int callingUid = Binder.getCallingUid(); final int callingUserId = UserHandle.getUserId(callingUid); final AndroidPackage pkg = mPackages.get(packageName); - if (pkg == null - || shouldFilterApplication(getPackageStateInternal(pkg.getPackageName()), - callingUid, callingUserId)) { + if (pkg == null || shouldFilterApplicationIncludingUninstalled( + getPackageStateInternal(pkg.getPackageName()), callingUid, callingUserId)) { Slog.w(TAG, "KeySet requested for unknown package: " + packageName + ", uid:" + callingUid); throw new IllegalArgumentException("Unknown package: " + packageName); @@ -5277,9 +5289,10 @@ public class ComputerEngine implements Computer { return false; } final AndroidPackage pkg = mPackages.get(packageName); + final int callingUserId = UserHandle.getUserId(callingUid); if (pkg == null - || shouldFilterApplication(getPackageStateInternal(pkg.getPackageName()), - callingUid, UserHandle.getUserId(callingUid))) { + || shouldFilterApplicationIncludingUninstalled( + getPackageStateInternal(pkg.getPackageName()), callingUid, callingUserId)) { Slog.w(TAG, "KeySet requested for unknown package: " + packageName); throw new IllegalArgumentException("Unknown package: " + packageName); } @@ -5301,9 +5314,10 @@ public class ComputerEngine implements Computer { return false; } final AndroidPackage pkg = mPackages.get(packageName); + final int callingUserId = UserHandle.getUserId(callingUid); if (pkg == null - || shouldFilterApplication(getPackageStateInternal(pkg.getPackageName()), - callingUid, UserHandle.getUserId(callingUid))) { + || shouldFilterApplicationIncludingUninstalled( + getPackageStateInternal(pkg.getPackageName()), callingUid, callingUserId)) { Slog.w(TAG, "KeySet requested for unknown package: " + packageName); throw new IllegalArgumentException("Unknown package: " + packageName); } @@ -5317,14 +5331,21 @@ public class ComputerEngine implements Computer { @Nullable @Override - public int[] getVisibilityAllowList(@NonNull String packageName, @UserIdInt int userId) { + public SparseArray<int[]> getVisibilityAllowLists(@NonNull String packageName, + @UserIdInt int[] userIds) { final PackageStateInternal ps = getPackageStateInternal(packageName, Process.SYSTEM_UID); if (ps == null) { return null; } - final SparseArray<int[]> visibilityAllowList = mAppsFilter.getVisibilityAllowList(ps, - new int[]{userId}, getPackageStates()); + return mAppsFilter.getVisibilityAllowList(ps, userIds, getPackageStates()); + } + + @Nullable + @Override + public int[] getVisibilityAllowList(@NonNull String packageName, @UserIdInt int userId) { + final SparseArray<int[]> visibilityAllowList = getVisibilityAllowLists(packageName, + new int[]{userId}); return visibilityAllowList != null ? visibilityAllowList.get(userId) : null; } diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java index d3d291ea52ac..7a490dcd8410 100644 --- a/services/core/java/com/android/server/pm/DeletePackageHelper.java +++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java @@ -39,7 +39,6 @@ import android.app.ApplicationPackageManager; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageDeleteObserver2; -import android.content.pm.PackageChangeEvent; import android.content.pm.PackageInstaller; import android.content.pm.PackageManager; import android.content.pm.SharedLibraryInfo; @@ -772,7 +771,6 @@ final class DeletePackageHelper { } catch (RemoteException e) { Log.i(TAG, "Observer no longer exists."); } //end catch - notifyPackageChangeObserversOnDelete(packageName, versionCode); // Prune unused static shared libraries which have been cached a period of time mPm.schedulePruneUnusedStaticSharedLibraries(true /* delay */); @@ -832,18 +830,6 @@ final class DeletePackageHelper { return result; } - private void notifyPackageChangeObserversOnDelete(String packageName, long version) { - PackageChangeEvent pkgChangeEvent = new PackageChangeEvent(); - pkgChangeEvent.packageName = packageName; - pkgChangeEvent.version = version; - pkgChangeEvent.lastUpdateTimeMillis = 0L; - pkgChangeEvent.newInstalled = false; - pkgChangeEvent.dataRemoved = false; - pkgChangeEvent.isDeleted = true; - - mPm.notifyPackageChangeObservers(pkgChangeEvent); - } - private static class TempUserState { public final int enabledState; @Nullable diff --git a/services/core/java/com/android/server/pm/DistractingPackageHelper.java b/services/core/java/com/android/server/pm/DistractingPackageHelper.java index 7dc45b58a773..b28b73e979fe 100644 --- a/services/core/java/com/android/server/pm/DistractingPackageHelper.java +++ b/services/core/java/com/android/server/pm/DistractingPackageHelper.java @@ -17,6 +17,7 @@ package com.android.server.pm; import static android.content.pm.PackageManager.RESTRICTION_NONE; +import static android.os.Process.SYSTEM_UID; import android.annotation.NonNull; import android.content.Intent; @@ -27,11 +28,13 @@ import android.os.UserHandle; import android.util.ArraySet; import android.util.IntArray; import android.util.Slog; +import android.util.SparseArray; import com.android.internal.util.ArrayUtils; import com.android.server.pm.pkg.PackageStateInternal; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; /** @@ -126,7 +129,7 @@ public final class DistractingPackageHelper { if (!changedPackagesList.isEmpty()) { final String[] changedPackages = changedPackagesList.toArray( new String[changedPackagesList.size()]); - sendDistractingPackagesChanged(changedPackages, changedUids.toArray(), userId, + sendDistractingPackagesChanged(snapshot, changedPackages, changedUids.toArray(), userId, restrictionFlags); mPm.scheduleWritePackageRestrictions(userId); } @@ -168,7 +171,7 @@ public final class DistractingPackageHelper { if (!changedPackages.isEmpty()) { final String[] packageArray = changedPackages.toArray( new String[changedPackages.size()]); - sendDistractingPackagesChanged(packageArray, changedUids.toArray(), userId, + sendDistractingPackagesChanged(snapshot, packageArray, changedUids.toArray(), userId, RESTRICTION_NONE); mPm.scheduleWritePackageRestrictions(userId); } @@ -181,18 +184,53 @@ public final class DistractingPackageHelper { * @param uidList The uids of packages which have suspension changes. * @param userId The user where packages reside. */ - void sendDistractingPackagesChanged(@NonNull String[] pkgList, + void sendDistractingPackagesChanged(@NonNull Computer snapshot, @NonNull String[] pkgList, int[] uidList, int userId, int distractionFlags) { - final Bundle extras = new Bundle(3); - extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgList); - extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidList); - extras.putInt(Intent.EXTRA_DISTRACTION_RESTRICTIONS, distractionFlags); + final List<List<String>> pkgsToSend = new ArrayList(pkgList.length); + final List<IntArray> uidsToSend = new ArrayList(pkgList.length); + final List<SparseArray<int[]>> allowListsToSend = new ArrayList(pkgList.length); + final int[] userIds = new int[] {userId}; + // Get allow lists for the pkg in the pkgList. Merge into the existed pkgs and uids if + // allow lists are the same. + for (int i = 0; i < pkgList.length; i++) { + final String pkgName = pkgList[i]; + final int uid = uidList[i]; + SparseArray<int[]> allowList = mInjector.getAppsFilter().getVisibilityAllowList( + snapshot.getPackageStateInternal(pkgName, SYSTEM_UID), + userIds, snapshot.getPackageStates()); + if (allowList == null) { + allowList = new SparseArray<>(0); + } + boolean merged = false; + for (int j = 0; j < allowListsToSend.size(); j++) { + if (Arrays.equals(allowListsToSend.get(j).get(userId), allowList.get(userId))) { + pkgsToSend.get(j).add(pkgName); + uidsToSend.get(j).add(uid); + merged = true; + break; + } + } + if (!merged) { + pkgsToSend.add(new ArrayList<>(Arrays.asList(pkgName))); + uidsToSend.add(IntArray.wrap(new int[] {uid})); + allowListsToSend.add(allowList); + } + } final Handler handler = mInjector.getHandler(); - handler.post(() -> mBroadcastHelper.sendPackageBroadcast( - Intent.ACTION_DISTRACTING_PACKAGES_CHANGED, null /* pkg */, extras, - Intent.FLAG_RECEIVER_REGISTERED_ONLY, null /* targetPkg */, - null /* finishedReceiver */, new int[]{userId}, null /* instantUserIds */, - null /* allowList */, null /* bOptions */)); + for (int i = 0; i < pkgsToSend.size(); i++) { + final Bundle extras = new Bundle(3); + extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, + pkgsToSend.get(i).toArray(new String[pkgsToSend.get(i).size()])); + extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidsToSend.get(i).toArray()); + extras.putInt(Intent.EXTRA_DISTRACTION_RESTRICTIONS, distractionFlags); + final SparseArray<int[]> allowList = allowListsToSend.get(i).size() == 0 + ? null : allowListsToSend.get(i); + handler.post(() -> mBroadcastHelper.sendPackageBroadcast( + Intent.ACTION_DISTRACTING_PACKAGES_CHANGED, null /* pkg */, + extras, Intent.FLAG_RECEIVER_REGISTERED_ONLY, null /* targetPkg */, + null /* finishedReceiver */, userIds, null /* instantUserIds */, + allowList, null /* bOptions */)); + } } } diff --git a/services/core/java/com/android/server/pm/DumpHelper.java b/services/core/java/com/android/server/pm/DumpHelper.java index 276644036def..0c3021396f55 100644 --- a/services/core/java/com/android/server/pm/DumpHelper.java +++ b/services/core/java/com/android/server/pm/DumpHelper.java @@ -52,6 +52,7 @@ import java.io.PrintWriter; final class DumpHelper { private final PermissionManagerServiceInternal mPermissionManager; private final ApexManager mApexManager; + private final ApexPackageInfo mApexPackageInfo; private final StorageEventHelper mStorageEventHelper; private final DomainVerificationManagerInternal mDomainVerificationManager; private final PackageInstallerService mInstallerService; @@ -64,6 +65,7 @@ final class DumpHelper { DumpHelper( PermissionManagerServiceInternal permissionManager, ApexManager apexManager, + ApexPackageInfo apexPackageInfo, StorageEventHelper storageEventHelper, DomainVerificationManagerInternal domainVerificationManager, PackageInstallerService installerService, String requiredVerifierPackage, @@ -74,6 +76,7 @@ final class DumpHelper { PerUidReadTimeouts[] perUidReadTimeouts) { mPermissionManager = permissionManager; mApexManager = apexManager; + mApexPackageInfo = apexPackageInfo; mStorageEventHelper = storageEventHelper; mDomainVerificationManager = domainVerificationManager; mInstallerService = installerService; @@ -271,7 +274,7 @@ final class DumpHelper { // Return if the package doesn't exist. if (packageName != null && snapshot.getPackageStateInternal(packageName) == null - && !mApexManager.isApexPackage(packageName)) { + && !mApexPackageInfo.isApexPackage(packageName)) { pw.println("Unable to find package: " + packageName); return; } @@ -555,8 +558,9 @@ final class DumpHelper { if (!checkin && dumpState.isDumping(DumpState.DUMP_APEX) - && (packageName == null || mApexManager.isApexPackage(packageName))) { + && (packageName == null || mApexPackageInfo.isApexPackage(packageName))) { mApexManager.dump(pw, packageName); + mApexPackageInfo.dump(pw, packageName); } if (!checkin diff --git a/services/core/java/com/android/server/pm/InitAppsHelper.java b/services/core/java/com/android/server/pm/InitAppsHelper.java index d279c77ad304..1b4c98103507 100644 --- a/services/core/java/com/android/server/pm/InitAppsHelper.java +++ b/services/core/java/com/android/server/pm/InitAppsHelper.java @@ -21,6 +21,7 @@ import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; import static com.android.internal.util.FrameworkStatsLog.BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_DATA_APP_AVG_SCAN_TIME; import static com.android.internal.util.FrameworkStatsLog.BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_SYSTEM_APP_AVG_SCAN_TIME; import static com.android.server.pm.PackageManagerService.SCAN_AS_APK_IN_APEX; +import static com.android.server.pm.PackageManagerService.SCAN_AS_FACTORY; import static com.android.server.pm.PackageManagerService.SCAN_AS_PRIVILEGED; import static com.android.server.pm.PackageManagerService.SCAN_AS_SYSTEM; import static com.android.server.pm.PackageManagerService.SCAN_BOOTING; @@ -71,6 +72,7 @@ final class InitAppsHelper { private final int mSystemScanFlags; private final InstallPackageHelper mInstallPackageHelper; private final ApexManager mApexManager; + private final ApexPackageInfo mApexPackageInfo; private final ExecutorService mExecutorService; /* Tracks how long system scan took */ private long mSystemScanTime; @@ -95,11 +97,13 @@ final class InitAppsHelper { private final List<String> mStubSystemApps = new ArrayList<>(); // TODO(b/198166813): remove PMS dependency - InitAppsHelper(PackageManagerService pm, ApexManager apexManager, + InitAppsHelper(PackageManagerService pm, + ApexManager apexManager, ApexPackageInfo apexPackageInfo, InstallPackageHelper installPackageHelper, List<ScanPartition> systemPartitions) { mPm = pm; mApexManager = apexManager; + mApexPackageInfo = apexPackageInfo; mInstallPackageHelper = installPackageHelper; mSystemPartitions = systemPartitions; mDirsToScanAsSystem = getSystemScanPartitions(); @@ -168,12 +172,37 @@ final class InitAppsHelper { sp.getFolder().getAbsolutePath()) || apexInfo.preInstalledApexPath.getAbsolutePath().startsWith( sp.getFolder().getAbsolutePath() + File.separator)) { - return new ScanPartition(apexInfo.apexDirectory, sp, SCAN_AS_APK_IN_APEX); + int additionalScanFlag = SCAN_AS_APK_IN_APEX; + if (apexInfo.isFactory) { + additionalScanFlag |= SCAN_AS_FACTORY; + } + return new ScanPartition(apexInfo.apexDirectory, sp, additionalScanFlag); } } return null; } + @GuardedBy({"mPm.mInstallLock", "mPm.mLock"}) + private List<ApexManager.ScanResult> scanApexPackagesTraced(PackageParser2 packageParser) { + Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanApexPackages"); + + try { + final List<ApexManager.ScanResult> apexScanResults; + if (ApexPackageInfo.ENABLE_FEATURE_SCAN_APEX) { + apexScanResults = mInstallPackageHelper.scanApexPackages( + mApexManager.getAllApexInfos(), mSystemParseFlags, mSystemScanFlags, + packageParser, mExecutorService); + mApexPackageInfo.notifyScanResult(apexScanResults); + } else { + apexScanResults = mApexPackageInfo.scanApexPackages( + mApexManager.getAllApexInfos(), packageParser, mExecutorService); + } + return apexScanResults; + } finally { + Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); + } + } + /** * Install apps from system dirs. */ @@ -183,7 +212,8 @@ final class InitAppsHelper { int[] userIds, long startTime) { // Prepare apex package info before scanning APKs, this information is needed when // scanning apk in apex. - mApexManager.scanApexPackagesTraced(packageParser, mExecutorService); + final List<ApexManager.ScanResult> apexScanResults = scanApexPackagesTraced(packageParser); + mApexManager.notifyScanResult(apexScanResults); scanSystemDirs(packageParser, mExecutorService); // Parse overlay configuration files to set default enable state, mutability, and diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java index bbdb7ebfe887..3410cec4e089 100644 --- a/services/core/java/com/android/server/pm/InstallPackageHelper.java +++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java @@ -59,7 +59,9 @@ import static com.android.server.pm.PackageManagerService.EMPTY_INT_ARRAY; import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME; import static com.android.server.pm.PackageManagerService.POST_INSTALL; import static com.android.server.pm.PackageManagerService.PRECOMPILE_LAYOUTS; +import static com.android.server.pm.PackageManagerService.SCAN_AS_APEX; import static com.android.server.pm.PackageManagerService.SCAN_AS_APK_IN_APEX; +import static com.android.server.pm.PackageManagerService.SCAN_AS_FACTORY; import static com.android.server.pm.PackageManagerService.SCAN_AS_FULL_APP; import static com.android.server.pm.PackageManagerService.SCAN_AS_INSTANT_APP; import static com.android.server.pm.PackageManagerService.SCAN_AS_ODM; @@ -91,6 +93,7 @@ import static com.android.server.pm.SharedUidMigration.BEST_EFFORT; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; +import android.apex.ApexInfo; import android.app.AppOpsManager; import android.app.ApplicationPackageManager; import android.app.backup.IBackupManager; @@ -101,7 +104,6 @@ import android.content.IntentSender; import android.content.pm.ApplicationInfo; import android.content.pm.DataLoaderType; import android.content.pm.IPackageInstallObserver2; -import android.content.pm.PackageChangeEvent; import android.content.pm.PackageInfo; import android.content.pm.PackageInfoLite; import android.content.pm.PackageInstaller; @@ -318,6 +320,12 @@ final class InstallPackageHelper { pkgSetting.setInstallSource(installSource); } + if ((scanFlags & SCAN_AS_APK_IN_APEX) != 0) { + boolean isFactory = (scanFlags & SCAN_AS_FACTORY) != 0; + pkgSetting.getPkgState().setApkInApex(true); + pkgSetting.getPkgState().setApkInUpdatedApex(!isFactory); + } + // TODO(toddke): Consider a method specifically for modifying the Package object // post scan; or, moving this stuff out of the Package object since it has nothing // to do with the package on disk. @@ -864,7 +872,17 @@ final class InstallPackageHelper { + " got: " + apexes.length); } try (PackageParser2 packageParser = mPm.mInjector.getScanningPackageParser()) { - mApexManager.installPackage(apexes[0], packageParser); + ApexInfo apexInfo = mApexManager.installPackage( + apexes[0], packageParser, mPm.mApexPackageInfo); + if (ApexPackageInfo.ENABLE_FEATURE_SCAN_APEX) { + ParsedPackage parsedPackage = packageParser.parsePackage( + new File(apexInfo.modulePath), 0, /* useCaches= */ false); + scanSystemPackageLI(parsedPackage, 0, SCAN_AS_APEX, null); + mPm.mApexPackageInfo.notifyPackageInstalled( + apexInfo, parsedPackage.hideAsFinal()); + } else { + mPm.mApexPackageInfo.notifyPackageInstalled(apexInfo, packageParser); + } } } catch (PackageManagerException e) { request.mInstallResult.setError("APEX installation failed", e); @@ -2344,29 +2362,11 @@ final class InstallPackageHelper { // BackgroundDexOptService will remove it from its denylist. // TODO: Layering violation BackgroundDexOptService.getService().notifyPackageChanged(packageName); - - notifyPackageChangeObserversOnUpdate(reconciledPkg); } PackageManagerServiceUtils.waitForNativeBinariesExtractionForIncremental( incrementalStorages); } - private void notifyPackageChangeObserversOnUpdate(ReconciledPackage reconciledPkg) { - final PackageSetting pkgSetting = reconciledPkg.mPkgSetting; - final PackageInstalledInfo pkgInstalledInfo = reconciledPkg.mInstallResult; - final PackageRemovedInfo pkgRemovedInfo = pkgInstalledInfo.mRemovedInfo; - - PackageChangeEvent pkgChangeEvent = new PackageChangeEvent(); - pkgChangeEvent.packageName = pkgSetting.getPkg().getPackageName(); - pkgChangeEvent.version = pkgSetting.getVersionCode(); - pkgChangeEvent.lastUpdateTimeMillis = pkgSetting.getLastUpdateTime(); - pkgChangeEvent.newInstalled = (pkgRemovedInfo == null || !pkgRemovedInfo.mIsUpdate); - pkgChangeEvent.dataRemoved = (pkgRemovedInfo != null && pkgRemovedInfo.mDataRemoved); - pkgChangeEvent.isDeleted = false; - - mPm.notifyPackageChangeObservers(pkgChangeEvent); - } - public int installLocationPolicy(PackageInfoLite pkgLite, int installFlags) { String packageName = pkgLite.packageName; int installLocation = pkgLite.installLocation; @@ -2469,7 +2469,7 @@ final class InstallPackageHelper { long requiredInstalledVersionCode, int installFlags) { String packageName = pkgLite.packageName; - final PackageInfo activePackage = mApexManager.getPackageInfo(packageName, + final PackageInfo activePackage = mPm.mApexPackageInfo.getPackageInfo(packageName, ApexManager.MATCH_ACTIVE_PACKAGE); if (activePackage == null) { String errorMsg = "Attempting to install new APEX package " + packageName; @@ -3390,6 +3390,56 @@ final class InstallPackageHelper { } } + public List<ApexManager.ScanResult> scanApexPackages(ApexInfo[] allPackages, int parseFlags, + int scanFlags, PackageParser2 packageParser, ExecutorService executorService) { + if (allPackages == null) { + return Collections.EMPTY_LIST; + } + + ParallelPackageParser parallelPackageParser = + new ParallelPackageParser(packageParser, executorService); + + // Submit files for parsing in parallel + ArrayMap<File, ApexInfo> parsingApexInfo = new ArrayMap<>(); + for (ApexInfo ai : allPackages) { + File apexFile = new File(ai.modulePath); + parallelPackageParser.submit(apexFile, parseFlags); + parsingApexInfo.put(apexFile, ai); + } + + // Process results one by one + List<ApexManager.ScanResult> results = new ArrayList<>(parsingApexInfo.size()); + for (int i = 0; i < parsingApexInfo.size(); i++) { + ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take(); + Throwable throwable = parseResult.throwable; + ApexInfo ai = parsingApexInfo.get(parseResult.scanFile); + int newScanFlags = scanFlags | SCAN_AS_APEX; + + if (throwable == null) { + try { + scanSystemPackageLI(parseResult.parsedPackage, parseFlags, newScanFlags, null); + AndroidPackage pkg = parseResult.parsedPackage.hideAsFinal(); + results.add(new ApexManager.ScanResult(ai, pkg, pkg.getPackageName())); + } catch (PackageManagerException e) { + throw new IllegalStateException("Failed to scan: " + ai.modulePath, e); + } + } else if (throwable instanceof PackageManagerException) { + final PackageManagerException e = (PackageManagerException) throwable; + // Skip parsing non-coreApp apex file if system is in minimal boot state. + if (e.error == PackageManager.INSTALL_PARSE_FAILED_ONLY_COREAPP_ALLOWED) { + Slog.w(TAG, "Scan apex failed, not a coreApp:" + ai.modulePath); + continue; + } + throw new IllegalStateException("Unable to parse: " + ai.modulePath, throwable); + } else { + throw new IllegalStateException("Unexpected exception occurred while parsing " + + ai.modulePath, throwable); + } + } + + return results; + } + @GuardedBy({"mPm.mInstallLock", "mPm.mLock"}) public void installPackagesFromDir(File scanDir, List<File> frameworkSplits, int parseFlags, int scanFlags, PackageParser2 packageParser, @@ -4091,8 +4141,12 @@ final class InstallPackageHelper { // after OTA. final boolean isUserInstall = (scanFlags & SCAN_BOOTING) == 0; final boolean isFirstBootOrUpgrade = (scanFlags & SCAN_FIRST_BOOT_OR_UPGRADE) != 0; + // It is allowed to install a new APEX with the same name. But there shouldn't be + // conflicting names between APK and APEX. + final boolean installApex = (scanFlags & SCAN_AS_APEX) != 0; if ((isUserInstall || isFirstBootOrUpgrade) - && mApexManager.isApexPackage(pkg.getPackageName())) { + && mPm.mApexPackageInfo.isApexPackage(pkg.getPackageName()) + && !installApex) { throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE, pkg.getPackageName() + " is an APEX package and can't be installed as an APK."); diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 7c900ef9401a..3e314a4e0f63 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -299,6 +299,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { final SessionParams params; final long createdMillis; + /** Used for tracking whether user action was required for an install. */ + @Nullable + private Boolean mUserActionRequired; + /** Staging location where client data is written. */ final File stageDir; final String stageCid; @@ -2131,8 +2135,16 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { * in its belong session set. When the user answers the yes, * {@link #setPermissionsResult(boolean)} is called and then {@link #MSG_INSTALL} is * handled to come back here to check again. + * + * {@code mUserActionRequired} is used to track when user action is required for an + * install. Since control may come back here more than 1 time, we must ensure that it's + * value is not overwritten. */ - if (sendPendingUserActionIntentIfNeeded()) { + boolean wasUserActionIntentSent = sendPendingUserActionIntentIfNeeded(); + if (mUserActionRequired == null) { + mUserActionRequired = wasUserActionIntentSent; + } + if (wasUserActionIntentSent) { return; } @@ -3323,6 +3335,18 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } } + /** + * @return a boolean value indicating whether user action was requested for the install. + * Returns {@code false} if {@code mUserActionRequired} is {@code null} + */ + public boolean getUserActionRequired() { + if (mUserActionRequired != null) { + return mUserActionRequired.booleanValue(); + } + Slog.wtf(TAG, "mUserActionRequired should not be null."); + return false; + } + private static String getRelativePath(File file, File base) throws IOException { final String pathStr = file.getAbsolutePath(); final String baseStr = base.getAbsolutePath(); diff --git a/services/core/java/com/android/server/pm/PackageManagerInternalBase.java b/services/core/java/com/android/server/pm/PackageManagerInternalBase.java index ec6443db9f0f..3d13db32b6fd 100644 --- a/services/core/java/com/android/server/pm/PackageManagerInternalBase.java +++ b/services/core/java/com/android/server/pm/PackageManagerInternalBase.java @@ -88,6 +88,7 @@ abstract class PackageManagerInternalBase extends PackageManagerInternal { @NonNull protected abstract UserNeedsBadgingCache getUserNeedsBadging(); @NonNull protected abstract InstantAppRegistry getInstantAppRegistry(); @NonNull protected abstract ApexManager getApexManager(); + @NonNull protected abstract ApexPackageInfo getApexPackageInfo(); @NonNull protected abstract DexManager getDexManager(); @Override @@ -638,7 +639,7 @@ abstract class PackageManagerInternalBase extends PackageManagerInternal { @Override @Deprecated public final boolean isApexPackage(String packageName) { - return getApexManager().isApexPackage(packageName); + return getApexPackageInfo().isApexPackage(packageName); } @Override diff --git a/services/core/java/com/android/server/pm/PackageManagerNative.java b/services/core/java/com/android/server/pm/PackageManagerNative.java index 9a43008acfdf..77d2ec970567 100644 --- a/services/core/java/com/android/server/pm/PackageManagerNative.java +++ b/services/core/java/com/android/server/pm/PackageManagerNative.java @@ -20,20 +20,16 @@ import static android.content.pm.PackageManager.CERT_INPUT_SHA256; import static com.android.server.pm.PackageManagerService.TAG; -import android.annotation.NonNull; import android.annotation.Nullable; import android.content.pm.ApplicationInfo; -import android.content.pm.IPackageChangeObserver; import android.content.pm.IPackageManagerNative; import android.content.pm.IStagedApexObserver; import android.content.pm.PackageInfo; import android.content.pm.StagedApexInfo; import android.os.Binder; -import android.os.IBinder; import android.os.RemoteException; import android.os.UserHandle; import android.text.TextUtils; -import android.util.Log; import android.util.Slog; import java.util.Arrays; @@ -46,35 +42,6 @@ final class PackageManagerNative extends IPackageManagerNative.Stub { } @Override - public void registerPackageChangeObserver(@NonNull IPackageChangeObserver observer) { - synchronized (mPm.mPackageChangeObservers) { - try { - observer.asBinder().linkToDeath( - new PackageChangeObserverDeathRecipient(observer), 0); - } catch (RemoteException e) { - Log.e(TAG, e.getMessage()); - } - mPm.mPackageChangeObservers.add(observer); - Log.d(TAG, "Size of mPackageChangeObservers after registry is " - + mPm.mPackageChangeObservers.size()); - } - } - - @Override - public void unregisterPackageChangeObserver(@NonNull IPackageChangeObserver observer) { - synchronized (mPm.mPackageChangeObservers) { - mPm.mPackageChangeObservers.remove(observer); - Log.d(TAG, "Size of mPackageChangeObservers after unregistry is " - + mPm.mPackageChangeObservers.size()); - } - } - - @Override - public String[] getAllPackages() { - return mPm.snapshotComputer().getAllPackages().toArray(new String[0]); - } - - @Override public String[] getNamesForUids(int[] uids) throws RemoteException { String[] names = null; String[] results = null; @@ -222,21 +189,4 @@ final class PackageManagerNative extends IPackageManagerNative.Stub { public StagedApexInfo getStagedApexInfo(String moduleName) { return mPm.mInstallerService.getStagingManager().getStagedApexInfo(moduleName); } - - private final class PackageChangeObserverDeathRecipient implements IBinder.DeathRecipient { - private final IPackageChangeObserver mObserver; - - PackageChangeObserverDeathRecipient(IPackageChangeObserver observer) { - mObserver = observer; - } - - @Override - public void binderDied() { - synchronized (mPm.mPackageChangeObservers) { - mPm.mPackageChangeObservers.remove(mObserver); - Log.d(TAG, "Size of mPackageChangeObservers after removing dead observer is " - + mPm.mPackageChangeObservers.size()); - } - } - } } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index ffd924edc7d8..1f3e03a9c72f 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -80,7 +80,6 @@ import android.content.pm.FallbackCategoryProvider; import android.content.pm.FeatureInfo; import android.content.pm.IDexModuleRegisterCallback; import android.content.pm.IOnChecksumsReadyListener; -import android.content.pm.IPackageChangeObserver; import android.content.pm.IPackageDataObserver; import android.content.pm.IPackageDeleteObserver2; import android.content.pm.IPackageInstallObserver2; @@ -92,7 +91,6 @@ import android.content.pm.InstallSourceInfo; import android.content.pm.InstantAppInfo; import android.content.pm.InstantAppRequest; import android.content.pm.ModuleInfo; -import android.content.pm.PackageChangeEvent; import android.content.pm.PackageInfo; import android.content.pm.PackageInfoLite; import android.content.pm.PackageInstaller; @@ -376,6 +374,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService static final int SCAN_AS_SYSTEM_EXT = 1 << 21; static final int SCAN_AS_ODM = 1 << 22; static final int SCAN_AS_APK_IN_APEX = 1 << 23; + static final int SCAN_AS_FACTORY = 1 << 24; + static final int SCAN_AS_APEX = 1 << 25; @IntDef(flag = true, prefix = { "SCAN_" }, value = { SCAN_NO_DEX, @@ -677,6 +677,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService private final ModuleInfoProvider mModuleInfoProvider; final ApexManager mApexManager; + final ApexPackageInfo mApexPackageInfo; final PackageManagerServiceInjector mInjector; @@ -690,10 +691,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService private @NonNull final OverlayConfig mOverlayConfig; - @GuardedBy("itself") - final ArrayList<IPackageChangeObserver> mPackageChangeObservers = - new ArrayList<>(); - // Cached parsed flag value. Invalidated on each flag change. PerUidReadTimeouts[] mPerUidReadTimeoutsCache; @@ -1611,6 +1608,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService mSharedLibraries = injector.getSharedLibrariesImpl(); mApexManager = testParams.apexManager; + mApexPackageInfo = new ApexPackageInfo(); mArtManagerService = testParams.artManagerService; mAvailableFeatures = testParams.availableFeatures; mBackgroundDexOptService = testParams.backgroundDexOptService; @@ -1814,6 +1812,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService mProtectedPackages = new ProtectedPackages(mContext); mApexManager = injector.getApexManager(); + mApexPackageInfo = new ApexPackageInfo(); mAppsFilter = mInjector.getAppsFilter(); mInstantAppRegistry = new InstantAppRegistry(mContext, mPermissionManager, @@ -1831,8 +1830,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService mAppDataHelper = new AppDataHelper(this); mInstallPackageHelper = new InstallPackageHelper(this, mAppDataHelper); mRemovePackageHelper = new RemovePackageHelper(this, mAppDataHelper); - mInitAppsHelper = new InitAppsHelper(this, mApexManager, mInstallPackageHelper, - mInjector.getSystemPartitions()); + mInitAppsHelper = new InitAppsHelper(this, mApexManager, mApexPackageInfo, + mInstallPackageHelper, mInjector.getSystemPartitions()); mDeletePackageHelper = new DeletePackageHelper(this, mRemovePackageHelper, mAppDataHelper); mSharedLibraries.setDeletePackageHelper(mDeletePackageHelper); @@ -1843,10 +1842,10 @@ public class PackageManagerService implements PackageSender, TestUtilityService mDexOptHelper = new DexOptHelper(this); mSuspendPackageHelper = new SuspendPackageHelper(this, mInjector, mBroadcastHelper, mProtectedPackages); - mStorageEventHelper = new StorageEventHelper(this, mDeletePackageHelper, - mRemovePackageHelper); mDistractingPackageHelper = new DistractingPackageHelper(this, mInjector, mBroadcastHelper, mSuspendPackageHelper); + mStorageEventHelper = new StorageEventHelper(this, mDeletePackageHelper, + mRemovePackageHelper); synchronized (mLock) { // Create the computer as soon as the state objects have been installed. The @@ -3142,23 +3141,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService }); } - void notifyPackageChangeObservers(PackageChangeEvent event) { - try { - Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "notifyPackageChangeObservers"); - synchronized (mPackageChangeObservers) { - for (IPackageChangeObserver observer : mPackageChangeObservers) { - try { - observer.onPackageChanged(event); - } catch (RemoteException e) { - Log.wtf(TAG, e); - } - } - } - } finally { - Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); - } - } - @SuppressWarnings("GuardedBy") VersionInfo getSettingsVersionForPackage(AndroidPackage pkg) { if (pkg.isExternalStorage()) { @@ -3962,8 +3944,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService snapshot.isInstantAppInternal(packageName, userId, Process.SYSTEM_UID); final int[] userIds = isInstantApp ? EMPTY_INT_ARRAY : new int[] { userId }; final int[] instantUserIds = isInstantApp ? new int[] { userId } : EMPTY_INT_ARRAY; - final SparseArray<int[]> broadcastAllowList = snapshot.getBroadcastAllowList( - packageName, userIds, isInstantApp); + final SparseArray<int[]> broadcastAllowList = + isInstantApp ? null : snapshot.getVisibilityAllowLists(packageName, userIds); mHandler.post(() -> mBroadcastHelper.sendPackageChangedBroadcast( packageName, dontKillApp, componentNames, packageUid, reason, userIds, instantUserIds, broadcastAllowList)); @@ -4988,8 +4970,12 @@ public class PackageManagerService implements PackageSender, TestUtilityService @Override public String getSplashScreenTheme(@NonNull String packageName, int userId) { final Computer snapshot = snapshotComputer(); + final int callingUid = Binder.getCallingUid(); + snapshot.enforceCrossUserPermission( + callingUid, userId, false /* requireFullPermission */, + false /* checkShell */, "getSplashScreenTheme"); PackageStateInternal packageState = filterPackageStateForInstalledAndFiltered(snapshot, - packageName, Binder.getCallingUid(), userId); + packageName, callingUid, userId); return packageState == null ? null : packageState.getUserStateOrDefault(userId).getSplashScreenTheme(); } @@ -5980,7 +5966,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService synchronized (mProtectedBroadcasts) { protectedBroadcasts = new ArraySet<>(mProtectedBroadcasts); } - new DumpHelper(mPermissionManager, mApexManager, mStorageEventHelper, + new DumpHelper(mPermissionManager, mApexManager, mApexPackageInfo, mStorageEventHelper, mDomainVerificationManager, mInstallerService, mRequiredVerifierPackage, knownPackages, mChangedPackagesTracker, availableFeatures, protectedBroadcasts, getPerUidReadTimeouts(snapshot) @@ -6081,6 +6067,12 @@ public class PackageManagerService implements PackageSender, TestUtilityService @NonNull @Override + protected ApexPackageInfo getApexPackageInfo() { + return mApexPackageInfo; + } + + @NonNull + @Override protected DexManager getDexManager() { return mDexManager; } @@ -6278,11 +6270,12 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override - public boolean setEnabledOverlayPackages(int userId, @NonNull String targetPackageName, - @Nullable OverlayPaths overlayPaths, - @NonNull Set<String> outUpdatedPackageNames) { - return PackageManagerService.this.setEnabledOverlayPackages(userId, targetPackageName, - overlayPaths, outUpdatedPackageNames); + public void setEnabledOverlayPackages(int userId, + @NonNull ArrayMap<String, OverlayPaths> pendingChanges, + @NonNull Set<String> outUpdatedPackageNames, + @NonNull Set<String> outInvalidPackageNames) { + PackageManagerService.this.setEnabledOverlayPackages(userId, + pendingChanges, outUpdatedPackageNames, outInvalidPackageNames); } @Override @@ -6346,7 +6339,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService return; } final ApexManager am = PackageManagerService.this.mApexManager; - PackageInfo activePackage = am.getPackageInfo(packageName, + final ApexPackageInfo api = PackageManagerService.this.mApexPackageInfo; + PackageInfo activePackage = api.getPackageInfo(packageName, ApexManager.MATCH_ACTIVE_PACKAGE); if (activePackage == null) { adapter.onPackageDeleted(packageName, PackageManager.DELETE_FAILED_ABORTED, @@ -6492,85 +6486,119 @@ public class PackageManagerService implements PackageSender, TestUtilityService } } - private boolean setEnabledOverlayPackages(@UserIdInt int userId, - @NonNull String targetPackageName, @Nullable OverlayPaths newOverlayPaths, - @NonNull Set<String> outUpdatedPackageNames) { + private void setEnabledOverlayPackages(@UserIdInt int userId, + @NonNull ArrayMap<String, OverlayPaths> pendingChanges, + @NonNull Set<String> outUpdatedPackageNames, + @NonNull Set<String> outInvalidPackageNames) { + final ArrayMap<String, ArrayMap<String, ArraySet<String>>> + targetPkgToLibNameToModifiedDependents = new ArrayMap<>(); + final int numberOfPendingChanges = pendingChanges.size(); + synchronized (mOverlayPathsLock) { - final ArrayMap<String, ArraySet<String>> libNameToModifiedDependents = new ArrayMap<>(); Computer computer = snapshotComputer(); - final PackageStateInternal packageState = computer.getPackageStateInternal( - targetPackageName); - final AndroidPackage targetPkg = packageState == null ? null : packageState.getPkg(); - if (targetPackageName == null || targetPkg == null) { - Slog.e(TAG, "failed to find package " + targetPackageName); - return false; - } + for (int i = 0; i < numberOfPendingChanges; i++) { + final String targetPackageName = pendingChanges.keyAt(i); + final OverlayPaths newOverlayPaths = pendingChanges.valueAt(i); + final PackageStateInternal packageState = computer.getPackageStateInternal( + targetPackageName); + final AndroidPackage targetPkg = + packageState == null ? null : packageState.getPkg(); + if (targetPackageName == null || targetPkg == null) { + Slog.e(TAG, "failed to find package " + targetPackageName); + outInvalidPackageNames.add(targetPackageName); + continue; + } - if (Objects.equals(packageState.getUserStateOrDefault(userId).getOverlayPaths(), - newOverlayPaths)) { - return true; - } + if (Objects.equals(packageState.getUserStateOrDefault(userId).getOverlayPaths(), + newOverlayPaths)) { + continue; + } - if (targetPkg.getLibraryNames() != null) { - // Set the overlay paths for dependencies of the shared library. - for (final String libName : targetPkg.getLibraryNames()) { - ArraySet<String> modifiedDependents = null; + if (targetPkg.getLibraryNames() != null) { + // Set the overlay paths for dependencies of the shared library. + for (final String libName : targetPkg.getLibraryNames()) { + ArraySet<String> modifiedDependents = null; - final SharedLibraryInfo info = computer.getSharedLibraryInfo(libName, - SharedLibraryInfo.VERSION_UNDEFINED); - if (info == null) { - continue; - } - final List<VersionedPackage> dependents = computer - .getPackagesUsingSharedLibrary(info, 0, Process.SYSTEM_UID, userId); - if (dependents == null) { - continue; - } - for (final VersionedPackage dependent : dependents) { - final PackageStateInternal dependentState = - computer.getPackageStateInternal(dependent.getPackageName()); - if (dependentState == null) { + final SharedLibraryInfo info = computer.getSharedLibraryInfo(libName, + SharedLibraryInfo.VERSION_UNDEFINED); + if (info == null) { continue; } - if (!Objects.equals(dependentState.getUserStateOrDefault(userId) - .getSharedLibraryOverlayPaths() - .get(libName), newOverlayPaths)) { - String dependentPackageName = dependent.getPackageName(); - modifiedDependents = ArrayUtils.add(modifiedDependents, - dependentPackageName); - outUpdatedPackageNames.add(dependentPackageName); + final List<VersionedPackage> dependents = + computer.getPackagesUsingSharedLibrary(info, 0, Process.SYSTEM_UID, + userId); + if (dependents == null) { + continue; + } + for (final VersionedPackage dependent : dependents) { + final PackageStateInternal dependentState = + computer.getPackageStateInternal(dependent.getPackageName()); + if (dependentState == null) { + continue; + } + if (!Objects.equals(dependentState.getUserStateOrDefault(userId) + .getSharedLibraryOverlayPaths() + .get(libName), newOverlayPaths)) { + String dependentPackageName = dependent.getPackageName(); + modifiedDependents = ArrayUtils.add(modifiedDependents, + dependentPackageName); + outUpdatedPackageNames.add(dependentPackageName); + } } - } - if (modifiedDependents != null) { - libNameToModifiedDependents.put(libName, modifiedDependents); + if (modifiedDependents != null) { + ArrayMap<String, ArraySet<String>> libNameToModifiedDependents = + targetPkgToLibNameToModifiedDependents.get( + targetPackageName); + if (libNameToModifiedDependents == null) { + libNameToModifiedDependents = new ArrayMap<>(); + targetPkgToLibNameToModifiedDependents.put(targetPackageName, + libNameToModifiedDependents); + } + libNameToModifiedDependents.put(libName, modifiedDependents); + } } } - } - outUpdatedPackageNames.add(targetPackageName); + outUpdatedPackageNames.add(targetPackageName); + } commitPackageStateMutation(null, mutator -> { - mutator.forPackage(targetPackageName) - .userState(userId) - .setOverlayPaths(newOverlayPaths); - - for (int mapIndex = 0; mapIndex < libNameToModifiedDependents.size(); mapIndex++) { - String libName = libNameToModifiedDependents.keyAt(mapIndex); - ArraySet<String> modifiedDependents = - libNameToModifiedDependents.valueAt(mapIndex); - for (int setIndex = 0; setIndex < modifiedDependents.size(); setIndex++) { - mutator.forPackage(modifiedDependents.valueAt(setIndex)) - .userState(userId) - .setOverlayPathsForLibrary(libName, newOverlayPaths); + for (int i = 0; i < numberOfPendingChanges; i++) { + final String targetPackageName = pendingChanges.keyAt(i); + final OverlayPaths newOverlayPaths = pendingChanges.valueAt(i); + + if (!outUpdatedPackageNames.contains(targetPackageName)) { + continue; + } + + mutator.forPackage(targetPackageName) + .userState(userId) + .setOverlayPaths(newOverlayPaths); + + final ArrayMap<String, ArraySet<String>> libNameToModifiedDependents = + targetPkgToLibNameToModifiedDependents.get( + targetPackageName); + if (libNameToModifiedDependents == null) { + continue; + } + + for (int mapIndex = 0; mapIndex < libNameToModifiedDependents.size(); + mapIndex++) { + String libName = libNameToModifiedDependents.keyAt(mapIndex); + ArraySet<String> modifiedDependents = + libNameToModifiedDependents.valueAt(mapIndex); + for (int setIndex = 0; setIndex < modifiedDependents.size(); setIndex++) { + mutator.forPackage(modifiedDependents.valueAt(setIndex)) + .userState(userId) + .setOverlayPathsForLibrary(libName, newOverlayPaths); + } } } }); } invalidatePackageInfoCache(); - - return true; } private void enforceAdjustRuntimePermissionsPolicyOrUpgradeRuntimePermissions( @@ -6609,9 +6637,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService @UserIdInt int userId) { PackageStateInternal packageState = computer.getPackageStateInternal(packageName, callingUid); - if (packageState == null - || computer.shouldFilterApplication(packageState, callingUid, userId) - || !packageState.getUserStateOrDefault(userId).isInstalled()) { + if (computer.shouldFilterApplicationIncludingUninstalled( + packageState, callingUid, userId)) { return null; } else { return packageState; diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java b/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java index 16829e0e8f6c..f44d922ea716 100644 --- a/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java +++ b/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java @@ -115,6 +115,6 @@ public final class PackageManagerServiceTestParams { public ResolveIntentHelper resolveIntentHelper; public DexOptHelper dexOptHelper; public SuspendPackageHelper suspendPackageHelper; - public StorageEventHelper storageEventHelper; public DistractingPackageHelper distractingPackageHelper; + public StorageEventHelper storageEventHelper; } diff --git a/services/core/java/com/android/server/pm/PackageSessionVerifier.java b/services/core/java/com/android/server/pm/PackageSessionVerifier.java index 2016fc3093b3..993417ada1b6 100644 --- a/services/core/java/com/android/server/pm/PackageSessionVerifier.java +++ b/services/core/java/com/android/server/pm/PackageSessionVerifier.java @@ -167,7 +167,7 @@ final class PackageSessionVerifier { } return new VerificationParams(user, session.stageDir, observer, session.params, session.getInstallSource(), session.getInstallerUid(), session.getSigningDetails(), - session.sessionId, session.getPackageLite(), mPm); + session.sessionId, session.getPackageLite(), session.getUserActionRequired(), mPm); } /** @@ -356,7 +356,7 @@ final class PackageSessionVerifier { final SigningDetails newSigningDetails = newResult.getResult(); // Get signing details of the existing package - final PackageInfo existingApexPkg = mApexManager.getPackageInfo(packageName, + final PackageInfo existingApexPkg = mPm.mApexPackageInfo.getPackageInfo(packageName, ApexManager.MATCH_ACTIVE_PACKAGE); if (existingApexPkg == null) { // This should never happen, because submitSessionToApexService ensures that no new diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java index 2bae00f91b82..f84db1f7abbe 100644 --- a/services/core/java/com/android/server/pm/PackageSetting.java +++ b/services/core/java/com/android/server/pm/PackageSetting.java @@ -1227,6 +1227,11 @@ public class PackageSetting extends SettingBase implements PackageStateInternal return pkgState.isUpdatedSystemApp(); } + @Override + public boolean isApkInUpdatedApex() { + return pkgState.isApkInUpdatedApex(); + } + public PackageSetting setDomainSetId(@NonNull UUID domainSetId) { mDomainSetId = domainSetId; onChanged(); diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index e6d59d43ffbe..9e960c3e027d 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -799,7 +799,6 @@ public final class Settings implements Watchable, Snappable { // always make sure the system package code and resource paths dont change if (dp == null && p.getPkg() != null && p.getPkg().isSystem() && !p.getPkgState().isUpdatedSystemApp()) { - p.getPkgState().setUpdatedSystemApp(true); final PackageSetting disabled; if (replaced) { // a little trick... when we install the new package, we don't @@ -810,6 +809,7 @@ public final class Settings implements Watchable, Snappable { } else { disabled = p; } + p.getPkgState().setUpdatedSystemApp(true); mDisabledSysPackages.put(name, disabled); SharedUserSetting sharedUserSetting = getSharedUserSettingLPr(disabled); if (sharedUserSetting != null) { diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java index b3723fb61f5a..f57eaaef25a4 100644 --- a/services/core/java/com/android/server/pm/ShortcutPackage.java +++ b/services/core/java/com/android/server/pm/ShortcutPackage.java @@ -894,8 +894,12 @@ class ShortcutPackage extends ShortcutPackageItem { // Get the list of all dynamic shortcuts in this package. final ArrayList<ShortcutInfo> shortcuts = new ArrayList<>(); + // Pass callingLauncher to ensure pinned flag marked by system ui, e.g. ShareSheet, are + // included in the result findAll(shortcuts, ShortcutInfo::isNonManifestVisible, - ShortcutInfo.CLONE_REMOVE_FOR_APP_PREDICTION); + ShortcutInfo.CLONE_REMOVE_FOR_APP_PREDICTION, + mShortcutUser.mService.mContext.getPackageName(), + 0, /*getPinnedByAnyLauncher=*/ false); final List<ShortcutManager.ShareShortcutInfo> result = new ArrayList<>(); for (int i = 0; i < shortcuts.size(); i++) { diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 358e71a70550..896df24393f4 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -1873,6 +1873,44 @@ public class UserManagerService extends IUserManager.Stub { } @Override + public boolean setUserEphemeral(@UserIdInt int userId, boolean enableEphemeral) { + checkCreateUsersPermission("update ephemeral user flag"); + UserData userToUpdate = null; + synchronized (mPackagesLock) { + synchronized (mUsersLock) { + final UserData userData = mUsers.get(userId); + if (userData == null) { + Slog.e(LOG_TAG, "User not found for setting ephemeral mode: u" + userId); + return false; + } + boolean isEphemeralUser = (userData.info.flags & UserInfo.FLAG_EPHEMERAL) != 0; + boolean isEphemeralOnCreateUser = + (userData.info.flags & UserInfo.FLAG_EPHEMERAL_ON_CREATE) != 0; + // when user is created in ephemeral mode via FLAG_EPHEMERAL + // its state cannot be changed to non ephemeral. + // FLAG_EPHEMERAL_ON_CREATE is used to keep track of this state + if (isEphemeralOnCreateUser && !enableEphemeral) { + Slog.e(LOG_TAG, "Failed to change user state to non-ephemeral for user " + + userId); + return false; + } + if (isEphemeralUser != enableEphemeral) { + if (enableEphemeral) { + userData.info.flags |= UserInfo.FLAG_EPHEMERAL; + } else { + userData.info.flags &= ~UserInfo.FLAG_EPHEMERAL; + } + userToUpdate = userData; + } + } + if (userToUpdate != null) { + writeUserLP(userToUpdate); + } + } + return true; + } + + @Override public void setUserIcon(@UserIdInt int userId, Bitmap bitmap) { try { checkManageUsersPermission("update users"); @@ -3979,6 +4017,10 @@ public class UserManagerService extends IUserManager.Stub { flags &= ~UserInfo.FLAG_EPHEMERAL; } + if ((flags & UserInfo.FLAG_EPHEMERAL) != 0) { + flags |= UserInfo.FLAG_EPHEMERAL_ON_CREATE; + } + userInfo = new UserInfo(userId, name, null, flags, userType); userInfo.serialNumber = mNextSerialNumber++; userInfo.creationTime = getCreationTime(); diff --git a/services/core/java/com/android/server/pm/VerificationParams.java b/services/core/java/com/android/server/pm/VerificationParams.java index 7423bf65c6a5..a3335609caf1 100644 --- a/services/core/java/com/android/server/pm/VerificationParams.java +++ b/services/core/java/com/android/server/pm/VerificationParams.java @@ -123,6 +123,7 @@ final class VerificationParams extends HandlerParams { final long mRequiredInstalledVersionCode; final int mDataLoaderType; final int mSessionId; + final boolean mUserActionRequired; private boolean mWaitForVerificationToComplete; private boolean mWaitForIntegrityVerificationToComplete; @@ -135,7 +136,7 @@ final class VerificationParams extends HandlerParams { VerificationParams(UserHandle user, File stagedDir, IPackageInstallObserver2 observer, PackageInstaller.SessionParams sessionParams, InstallSource installSource, int installerUid, SigningDetails signingDetails, int sessionId, PackageLite lite, - PackageManagerService pm) { + boolean userActionRequired, PackageManagerService pm) { super(user, pm); mOriginInfo = OriginInfo.fromStagedFile(stagedDir); mObserver = observer; @@ -154,6 +155,7 @@ final class VerificationParams extends HandlerParams { ? sessionParams.dataLoaderParams.getType() : DataLoaderType.NONE; mSessionId = sessionId; mPackageLite = lite; + mUserActionRequired = userActionRequired; } @Override @@ -430,6 +432,8 @@ final class VerificationParams extends HandlerParams { verification.putExtra(PackageInstaller.EXTRA_SESSION_ID, mSessionId); + verification.putExtra(PackageManager.EXTRA_USER_ACTION_REQUIRED, mUserActionRequired); + populateInstallerExtras(verification); // Streaming installation timeout schema is enabled only for: diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index 5a05134bed81..5d6ebec6cc30 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -277,10 +277,6 @@ public class PermissionManagerService extends IPermissionManager.Stub { } private boolean checkAutoRevokeAccess(AndroidPackage pkg, int callingUid) { - if (pkg == null) { - return false; - } - final boolean isCallerPrivileged = mContext.checkCallingOrSelfPermission( Manifest.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS) == PackageManager.PERMISSION_GRANTED; @@ -292,6 +288,12 @@ public class PermissionManagerService extends IPermissionManager.Stub { + Manifest.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS + " or be the installer on record"); } + + if (pkg == null || mPackageManagerInt.filterAppAccess(pkg, callingUid, + UserHandle.getUserId(callingUid))) { + return false; + } + return true; } @@ -301,9 +303,6 @@ public class PermissionManagerService extends IPermissionManager.Stub { final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName); final int callingUid = Binder.getCallingUid(); - if (mPackageManagerInt.filterAppAccess(packageName, callingUid, userId)) { - return false; - } if (!checkAutoRevokeAccess(pkg, callingUid)) { return false; diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java index 092f3bec4012..f91d1b1f6a49 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java @@ -47,7 +47,6 @@ import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; import static android.permission.PermissionManager.KILL_APP_REASON_GIDS_CHANGED; import static android.permission.PermissionManager.KILL_APP_REASON_PERMISSIONS_REVOKED; -import static com.android.server.pm.ApexManager.MATCH_ACTIVE_PACKAGE; import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL; import static com.android.server.pm.PackageManagerService.DEBUG_PACKAGE_SCANNING; import static com.android.server.pm.PackageManagerService.DEBUG_PERMISSIONS; @@ -574,9 +573,11 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt return null; } + final ParsedPermissionGroup permissionGroup; final List<PermissionInfo> out = new ArrayList<>(10); synchronized (mLock) { - if (groupName != null && mRegistry.getPermissionGroup(groupName) == null) { + permissionGroup = mRegistry.getPermissionGroup(groupName); + if (groupName != null && permissionGroup == null) { return null; } for (Permission bp : mRegistry.getPermissions()) { @@ -587,6 +588,10 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt } final int callingUserId = UserHandle.getUserId(callingUid); + if (mPackageManagerInt.filterAppAccess(permissionGroup.getPackageName(), callingUid, + callingUserId)) { + return null; + } out.removeIf(it -> mPackageManagerInt.filterAppAccess(it.packageName, callingUid, callingUserId)); return out; @@ -3255,9 +3260,7 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt } // Only enforce the allowlist on boot if (!mSystemReady) { - final boolean isInUpdatedApex = containingApexPackageName != null - && !apexManager.isFactory(apexManager.getPackageInfo(containingApexPackageName, - MATCH_ACTIVE_PACKAGE)); + final boolean isInUpdatedApex = packageSetting.isApkInUpdatedApex(); // Apps that are in updated apexs' do not need to be allowlisted if (!isInUpdatedApex) { Slog.w(TAG, "Privileged permission " + permissionName + " for package " diff --git a/services/core/java/com/android/server/pm/pkg/PackageState.java b/services/core/java/com/android/server/pm/pkg/PackageState.java index 7726d7fc226b..b5e0e4416fe4 100644 --- a/services/core/java/com/android/server/pm/pkg/PackageState.java +++ b/services/core/java/com/android/server/pm/pkg/PackageState.java @@ -303,6 +303,11 @@ public interface PackageState { boolean isUpdatedSystemApp(); /** + * Whether this app is packaged in an updated apex. + */ + boolean isApkInUpdatedApex(); + + /** * @see AndroidPackageApi#isVendor() */ boolean isVendor(); diff --git a/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java b/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java index 3170304985b5..878a837585ca 100644 --- a/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java +++ b/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java @@ -71,6 +71,7 @@ public class PackageStateImpl implements PackageState { INSTALL_PERMISSIONS_FIXED, UPDATE_AVAILABLE, UPDATED_SYSTEM_APP, + APK_IN_UPDATED_APEX, }) public @interface Flags { } @@ -89,6 +90,7 @@ public class PackageStateImpl implements PackageState { private static final int INSTALL_PERMISSIONS_FIXED = 1 << 11; private static final int UPDATE_AVAILABLE = 1 << 12; private static final int UPDATED_SYSTEM_APP = 1 << 13; + private static final int APK_IN_UPDATED_APEX = 1 << 14; } private int mBooleans; @@ -187,6 +189,7 @@ public class PackageStateImpl implements PackageState { setBoolean(Booleans.UPDATE_AVAILABLE, pkgState.isUpdateAvailable()); mLastPackageUsageTime = pkgState.getLastPackageUsageTime(); setBoolean(Booleans.UPDATED_SYSTEM_APP, pkgState.isUpdatedSystemApp()); + setBoolean(Booleans.APK_IN_UPDATED_APEX, pkgState.isApkInUpdatedApex()); mSigningInfo = pkgState.getSigningInfo(); SparseArray<? extends PackageUserState> userStates = pkgState.getUserStates(); @@ -264,6 +267,11 @@ public class PackageStateImpl implements PackageState { } @Override + public boolean isApkInUpdatedApex() { + return getBoolean(Booleans.APK_IN_UPDATED_APEX); + } + + @Override public boolean isVendor() { return getBoolean(Booleans.VENDOR); } diff --git a/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java b/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java index 7bd720acc799..fad2f857f656 100644 --- a/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java +++ b/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java @@ -52,6 +52,8 @@ public class PackageStateUnserialized { private List<String> usesLibraryFiles = emptyList(); private boolean updatedSystemApp; + private boolean apkInApex; + private boolean apkInUpdatedApex; @NonNull private volatile long[] lastPackageUsageTimeInMills; @@ -116,6 +118,8 @@ public class PackageStateUnserialized { } this.updatedSystemApp = other.updatedSystemApp; + this.apkInApex = other.apkInApex; + this.apkInUpdatedApex = other.apkInUpdatedApex; this.lastPackageUsageTimeInMills = other.lastPackageUsageTimeInMills; this.overrideSeInfo = other.overrideSeInfo; mPackageSetting.onChanged(); @@ -150,6 +154,18 @@ public class PackageStateUnserialized { return this; } + public PackageStateUnserialized setApkInApex(boolean value) { + apkInApex = value; + mPackageSetting.onChanged(); + return this; + } + + public PackageStateUnserialized setApkInUpdatedApex(boolean value) { + apkInUpdatedApex = value; + mPackageSetting.onChanged(); + return this; + } + public PackageStateUnserialized setLastPackageUsageTimeInMills(@NonNull long... value) { lastPackageUsageTimeInMills = value; mPackageSetting.onChanged(); @@ -198,6 +214,16 @@ public class PackageStateUnserialized { } @DataClass.Generated.Member + public boolean isApkInApex() { + return apkInApex; + } + + @DataClass.Generated.Member + public boolean isApkInUpdatedApex() { + return apkInUpdatedApex; + } + + @DataClass.Generated.Member public @NonNull long[] getLastPackageUsageTimeInMills() { long[] _lastPackageUsageTimeInMills = lastPackageUsageTimeInMills; if (_lastPackageUsageTimeInMills == null) { @@ -222,10 +248,10 @@ public class PackageStateUnserialized { } @DataClass.Generated( - time = 1642554781099L, + time = 1646203523807L, codegenVersion = "1.0.23", sourceFile = "frameworks/base/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java", - inputSignatures = "private boolean hiddenUntilInstalled\nprivate @android.annotation.NonNull java.util.List<android.content.pm.SharedLibraryInfo> usesLibraryInfos\nprivate @android.annotation.NonNull java.util.List<java.lang.String> usesLibraryFiles\nprivate boolean updatedSystemApp\nprivate volatile @android.annotation.NonNull long[] lastPackageUsageTimeInMills\nprivate @android.annotation.Nullable java.lang.String overrideSeInfo\nprivate @android.annotation.NonNull com.android.server.pm.PackageSetting mPackageSetting\nprivate long[] lazyInitLastPackageUsageTimeInMills()\npublic com.android.server.pm.pkg.PackageStateUnserialized setLastPackageUsageTimeInMills(int,long)\npublic long getLatestPackageUseTimeInMills()\npublic long getLatestForegroundPackageUseTimeInMills()\npublic void updateFrom(com.android.server.pm.pkg.PackageStateUnserialized)\npublic @android.annotation.NonNull java.util.List<android.content.pm.SharedLibraryInfo> getNonNativeUsesLibraryInfos()\npublic com.android.server.pm.pkg.PackageStateUnserialized setHiddenUntilInstalled(boolean)\npublic com.android.server.pm.pkg.PackageStateUnserialized setUsesLibraryInfos(java.util.List<android.content.pm.SharedLibraryInfo>)\npublic com.android.server.pm.pkg.PackageStateUnserialized setUsesLibraryFiles(java.util.List<java.lang.String>)\npublic com.android.server.pm.pkg.PackageStateUnserialized setUpdatedSystemApp(boolean)\npublic com.android.server.pm.pkg.PackageStateUnserialized setLastPackageUsageTimeInMills(long)\npublic com.android.server.pm.pkg.PackageStateUnserialized setOverrideSeInfo(java.lang.String)\nclass PackageStateUnserialized extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genSetters=true, genConstructor=false, genBuilder=false)") + inputSignatures = "private boolean hiddenUntilInstalled\nprivate @android.annotation.NonNull java.util.List<android.content.pm.SharedLibraryInfo> usesLibraryInfos\nprivate @android.annotation.NonNull java.util.List<java.lang.String> usesLibraryFiles\nprivate boolean updatedSystemApp\nprivate boolean apkInApex\nprivate boolean apkInUpdatedApex\nprivate volatile @android.annotation.NonNull long[] lastPackageUsageTimeInMills\nprivate @android.annotation.Nullable java.lang.String overrideSeInfo\nprivate final @android.annotation.NonNull com.android.server.pm.PackageSetting mPackageSetting\nprivate long[] lazyInitLastPackageUsageTimeInMills()\npublic com.android.server.pm.pkg.PackageStateUnserialized setLastPackageUsageTimeInMills(int,long)\npublic long getLatestPackageUseTimeInMills()\npublic long getLatestForegroundPackageUseTimeInMills()\npublic void updateFrom(com.android.server.pm.pkg.PackageStateUnserialized)\npublic @android.annotation.NonNull java.util.List<android.content.pm.SharedLibraryInfo> getNonNativeUsesLibraryInfos()\npublic com.android.server.pm.pkg.PackageStateUnserialized setHiddenUntilInstalled(boolean)\npublic com.android.server.pm.pkg.PackageStateUnserialized setUsesLibraryInfos(java.util.List<android.content.pm.SharedLibraryInfo>)\npublic com.android.server.pm.pkg.PackageStateUnserialized setUsesLibraryFiles(java.util.List<java.lang.String>)\npublic com.android.server.pm.pkg.PackageStateUnserialized setUpdatedSystemApp(boolean)\npublic com.android.server.pm.pkg.PackageStateUnserialized setApkInApex(boolean)\npublic com.android.server.pm.pkg.PackageStateUnserialized setApkInUpdatedApex(boolean)\npublic com.android.server.pm.pkg.PackageStateUnserialized setLastPackageUsageTimeInMills(long)\npublic com.android.server.pm.pkg.PackageStateUnserialized setOverrideSeInfo(java.lang.String)\nclass PackageStateUnserialized extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genSetters=true, genConstructor=false, genBuilder=false)") @Deprecated private void __metadata() {} diff --git a/services/core/java/com/android/server/pm/pkg/parsing/PackageInfoWithoutStateUtils.java b/services/core/java/com/android/server/pm/pkg/parsing/PackageInfoWithoutStateUtils.java index 91d201096fcd..8a64884ad6a5 100644 --- a/services/core/java/com/android/server/pm/pkg/parsing/PackageInfoWithoutStateUtils.java +++ b/services/core/java/com/android/server/pm/pkg/parsing/PackageInfoWithoutStateUtils.java @@ -321,19 +321,15 @@ public class PackageInfoWithoutStateUtils { pi.applicationInfo.sourceDir = apexFile.getPath(); pi.applicationInfo.publicSourceDir = apexFile.getPath(); + pi.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM; + pi.applicationInfo.flags |= ApplicationInfo.FLAG_INSTALLED; if (apexInfo.isFactory) { - pi.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM; pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; } else { - pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM; pi.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; } - if (apexInfo.isActive) { - pi.applicationInfo.flags |= ApplicationInfo.FLAG_INSTALLED; - } else { - pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED; - } pi.isApex = true; + pi.isActiveApex = apexInfo.isActive; } final SigningDetails signingDetails = pkg.getSigningDetails(); diff --git a/services/core/java/com/android/server/pm/verify/domain/TEST_MAPPING b/services/core/java/com/android/server/pm/verify/domain/TEST_MAPPING index ba4a62cdbbf1..8a1982a339ea 100644 --- a/services/core/java/com/android/server/pm/verify/domain/TEST_MAPPING +++ b/services/core/java/com/android/server/pm/verify/domain/TEST_MAPPING @@ -12,9 +12,6 @@ "name": "CtsDomainVerificationDeviceStandaloneTestCases" }, { - "name": "CtsDomainVerificationDeviceMultiUserTestCases" - }, - { "name": "CtsDomainVerificationHostTestCases" } ] diff --git a/services/core/java/com/android/server/policy/GlobalKeyManager.java b/services/core/java/com/android/server/policy/GlobalKeyManager.java index b9bd9f132dbc..ca2897eb4b6e 100644 --- a/services/core/java/com/android/server/policy/GlobalKeyManager.java +++ b/services/core/java/com/android/server/policy/GlobalKeyManager.java @@ -137,20 +137,27 @@ final class GlobalKeyManager { String componentName = parser.getAttributeValue(null, ATTR_COMPONENT); String dispatchWhenNonInteractive = parser.getAttributeValue(null, ATTR_DISPATCH_WHEN_NON_INTERACTIVE); + if (keyCodeName == null || componentName == null) { + Log.wtf(TAG, "Failed to parse global keys entry: " + parser.getText()); + continue; + } int keyCode = KeyEvent.keyCodeFromString(keyCodeName); if (keyCode != KeyEvent.KEYCODE_UNKNOWN) { mKeyMapping.put(keyCode, new GlobalKeyAction( componentName, dispatchWhenNonInteractive)); + } else { + Log.wtf(TAG, "Global keys entry does not map to a valid key code: " + + keyCodeName); } } } } } catch (Resources.NotFoundException e) { - Log.w(TAG, "global keys file not found", e); + Log.wtf(TAG, "global keys file not found", e); } catch (XmlPullParserException e) { - Log.w(TAG, "XML parser exception reading global keys file", e); + Log.wtf(TAG, "XML parser exception reading global keys file", e); } catch (IOException e) { - Log.w(TAG, "I/O exception reading global keys file", e); + Log.e(TAG, "I/O exception reading global keys file", e); } } diff --git a/services/core/java/com/android/server/power/ShutdownCheckPoints.java b/services/core/java/com/android/server/power/ShutdownCheckPoints.java index 05ee7dfb4cae..1a9eae6b6d8d 100644 --- a/services/core/java/com/android/server/power/ShutdownCheckPoints.java +++ b/services/core/java/com/android/server/power/ShutdownCheckPoints.java @@ -36,7 +36,6 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; -import java.util.LinkedList; import java.util.List; /** @@ -56,7 +55,7 @@ public final class ShutdownCheckPoints { private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS z"); - private final LinkedList<CheckPoint> mCheckPoints; + private final ArrayList<CheckPoint> mCheckPoints; private final Injector mInjector; private ShutdownCheckPoints() { @@ -85,7 +84,7 @@ public final class ShutdownCheckPoints { @VisibleForTesting ShutdownCheckPoints(Injector injector) { - mCheckPoints = new LinkedList<>(); + mCheckPoints = new ArrayList<>(); mInjector = injector; } @@ -144,8 +143,8 @@ public final class ShutdownCheckPoints { private void recordCheckPointInternal(CheckPoint checkPoint) { synchronized (mCheckPoints) { - mCheckPoints.addLast(checkPoint); - if (mCheckPoints.size() > mInjector.maxCheckPoints()) mCheckPoints.removeFirst(); + mCheckPoints.add(checkPoint); + if (mCheckPoints.size() > mInjector.maxCheckPoints()) mCheckPoints.remove(0); } } diff --git a/services/core/java/com/android/server/security/AndroidKeystoreAttestationVerificationAttributes.java b/services/core/java/com/android/server/security/AndroidKeystoreAttestationVerificationAttributes.java index 3543e9319a88..928d128d6d16 100644 --- a/services/core/java/com/android/server/security/AndroidKeystoreAttestationVerificationAttributes.java +++ b/services/core/java/com/android/server/security/AndroidKeystoreAttestationVerificationAttributes.java @@ -32,6 +32,7 @@ import com.android.internal.org.bouncycastle.asn1.ASN1Set; import com.android.internal.org.bouncycastle.asn1.ASN1TaggedObject; import com.android.internal.org.bouncycastle.asn1.x509.Certificate; +import java.io.IOException; import java.nio.charset.StandardCharsets; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; @@ -147,7 +148,7 @@ class AndroidKeystoreAttestationVerificationAttributes { @NonNull static AndroidKeystoreAttestationVerificationAttributes fromCertificate( @NonNull X509Certificate x509Certificate) - throws Exception { + throws CertificateEncodingException, IOException { return new AndroidKeystoreAttestationVerificationAttributes(x509Certificate); } @@ -281,7 +282,7 @@ class AndroidKeystoreAttestationVerificationAttributes { } private AndroidKeystoreAttestationVerificationAttributes(X509Certificate x509Certificate) - throws Exception { + throws CertificateEncodingException, IOException { Certificate certificate = Certificate.getInstance( new ASN1InputStream(x509Certificate.getEncoded()).readObject()); ASN1Sequence keyAttributes = (ASN1Sequence) certificate.getTBSCertificate().getExtensions() @@ -380,7 +381,7 @@ class AndroidKeystoreAttestationVerificationAttributes { } private void parseAttestationApplicationId(byte [] attestationApplicationId) - throws Exception { + throws IOException { ASN1Sequence outerSequence = ASN1Sequence.getInstance( new ASN1InputStream(attestationApplicationId).readObject()); Map<String, Long> packageNameVersion = new HashMap<>(); diff --git a/services/core/java/com/android/server/security/AttestationVerificationPeerDeviceVerifier.java b/services/core/java/com/android/server/security/AttestationVerificationPeerDeviceVerifier.java index 0f8be5a77944..bcc39ba1bde1 100644 --- a/services/core/java/com/android/server/security/AttestationVerificationPeerDeviceVerifier.java +++ b/services/core/java/com/android/server/security/AttestationVerificationPeerDeviceVerifier.java @@ -22,8 +22,10 @@ import static android.security.attestationverification.AttestationVerificationMa import static android.security.attestationverification.AttestationVerificationManager.RESULT_SUCCESS; import static android.security.attestationverification.AttestationVerificationManager.TYPE_CHALLENGE; import static android.security.attestationverification.AttestationVerificationManager.TYPE_PUBLIC_KEY; +import static android.security.attestationverification.AttestationVerificationManager.localBindingTypeToString; import static com.android.server.security.AndroidKeystoreAttestationVerificationAttributes.VerifiedBootState.VERIFIED; +import static com.android.server.security.AndroidKeystoreAttestationVerificationAttributes.fromCertificate; import static java.nio.charset.StandardCharsets.UTF_8; @@ -31,6 +33,7 @@ import android.annotation.NonNull; import android.content.Context; import android.os.Build; import android.os.Bundle; +import android.security.attestationverification.AttestationVerificationManager.LocalBindingType; import android.util.Log; import android.util.Slog; @@ -40,8 +43,10 @@ import com.android.internal.annotations.VisibleForTesting; import org.json.JSONObject; import java.io.ByteArrayInputStream; +import java.io.IOException; import java.io.InputStream; import java.net.URL; +import java.security.InvalidAlgorithmParameterException; import java.security.cert.CertPath; import java.security.cert.CertPathValidator; import java.security.cert.CertPathValidatorException; @@ -65,17 +70,26 @@ import java.util.Objects; import java.util.Set; /** - * Verifies Android key attestation according to the {@code PROFILE_PEER_DEVICE} profile. + * Verifies Android key attestation according to the + * {@link android.security.attestationverification.AttestationVerificationManager#PROFILE_PEER_DEVICE PROFILE_PEER_DEVICE} + * profile. * - * Trust anchors are vendor-defined via the vendor_required_attestation_certificates.xml resource. + * <p> * The profile is satisfied by checking all the following: - * * TrustAnchor match - * * Certificate validity - * * Android OS 10 or higher - * * Hardware backed key store - * * Verified boot locked - * * Remote Patch level must be within 1 year of local patch if local patch is less than 1 year old. + * <ul> + * <li> TrustAnchor match + * <li> Certificate validity + * <li> Android OS 10 or higher + * <li> Hardware backed key store + * <li> Verified boot locked + * <li> Remote Patch level must be within 1 year of local patch if local patch is less than 1 year + * old. + * </ul> * + * <p> + * Trust anchors are vendor-defined by populating + * {@link R.array#vendor_required_attestation_certificates} string array (defenined in + * {@code frameworks/base/core/res/res/values/vendor_required_attestation_certificates.xml}). */ class AttestationVerificationPeerDeviceVerifier { private static final String TAG = "AVF"; @@ -87,20 +101,8 @@ class AttestationVerificationPeerDeviceVerifier { private final boolean mRevocationEnabled; private final LocalDate mTestSystemDate; private final LocalDate mTestLocalPatchDate; - private CertificateFactory mCertificateFactory; - private CertPathValidator mCertPathValidator; - - private static void debugVerboseLog(String str, Throwable t) { - if (DEBUG) { - Slog.v(TAG, str, t); - } - } - - private static void debugVerboseLog(String str) { - if (DEBUG) { - Slog.v(TAG, str); - } - } + private final CertificateFactory mCertificateFactory; + private final CertPathValidator mCertPathValidator; AttestationVerificationPeerDeviceVerifier(@NonNull Context context) throws Exception { mContext = Objects.requireNonNull(context); @@ -128,53 +130,71 @@ class AttestationVerificationPeerDeviceVerifier { /** * Verifies attestation for public key or challenge local binding. - * + * <p> * The attestations must be suitable for {@link java.security.cert.CertificateFactory} * The certificates in the attestation provided must be DER-encoded and may be supplied in * binary or printable (Base64) encoding. If the certificate is provided in Base64 encoding, - * it must be bounded at the beginning by -----BEGIN CERTIFICATE-----, and must be bounded at - * the end by -----END CERTIFICATE-----. + * it must be bounded at the beginning by {@code -----BEGIN CERTIFICATE-----}, and must be + * bounded at the end by {@code -----END CERTIFICATE-----}. * * @param localBindingType Only {@code TYPE_PUBLIC_KEY} and {@code TYPE_CHALLENGE} supported. * @param requirements Only {@code PARAM_PUBLIC_KEY} and {@code PARAM_CHALLENGE} supported. * @param attestation Certificates should be DER encoded with leaf certificate appended first. */ int verifyAttestation( - int localBindingType, @NonNull Bundle requirements, @NonNull byte[] attestation) { - int status = RESULT_FAILURE; - + @LocalBindingType int localBindingType, + @NonNull Bundle requirements, + @NonNull byte[] attestation) { if (mCertificateFactory == null) { - debugVerboseLog("Was unable to initialize CertificateFactory onCreate."); - return status; + debugVerboseLog("Unable to access CertificateFactory"); + return RESULT_FAILURE; } if (mCertPathValidator == null) { - debugVerboseLog("Was unable to initialize CertPathValidator onCreate."); - return status; + debugVerboseLog("Unable to access CertPathValidator"); + return RESULT_FAILURE; } - List<X509Certificate> certificates; - try { - certificates = getCertificates(attestation); - } catch (CertificateException e) { - debugVerboseLog("Unable to parse attestation certificates.", e); - return status; + // Check if the provided local binding type is supported and if the provided requirements + // "match" the binding type. + if (!validateAttestationParameters(localBindingType, requirements)) { + return RESULT_FAILURE; } - if (certificates.isEmpty()) { - debugVerboseLog("Attestation contains no certificates."); - return status; - } + try { + // First: parse and validate the certificate chain. + final List<X509Certificate> certificateChain = getCertificates(attestation); + // (returns void, but throws CertificateException and other similar Exceptions) + validateCertificateChain(certificateChain); - X509Certificate leafNode = certificates.get(0); - if (validateRequirements(localBindingType, requirements) - && validateCertificateChain(certificates) - && checkCertificateAttributes(leafNode, localBindingType, requirements)) { - status = RESULT_SUCCESS; - } else { - status = RESULT_FAILURE; + final var leafCertificate = certificateChain.get(0); + final var attestationExtension = fromCertificate(leafCertificate); + + // Second: verify if the attestation satisfies the "peer device" porfile. + if (!checkAttestationForPeerDeviceProfile(attestationExtension)) { + return RESULT_FAILURE; + } + + // Third: check if the attestation satisfies local binding requirements. + if (!checkLocalBindingRequirements( + leafCertificate, attestationExtension, localBindingType, requirements)) { + return RESULT_FAILURE; + } + + return RESULT_SUCCESS; + } catch (CertificateException | CertPathValidatorException + | InvalidAlgorithmParameterException | IOException e) { + // Catch all non-RuntimeExpceptions (all of these are thrown by either getCertificates() + // or validateCertificateChain() or + // AndroidKeystoreAttestationVerificationAttributes.fromCertificate()) + debugVerboseLog("Unable to parse/validate Android Attestation certificate(s)", e); + return RESULT_FAILURE; + } catch (RuntimeException e) { + // Catch everyting else (RuntimeExpcetions), since we don't want to throw any exceptions + // out of this class/method. + debugVerboseLog("Unexpected error", e); + return RESULT_FAILURE; } - return status; } @NonNull @@ -189,14 +209,19 @@ class AttestationVerificationPeerDeviceVerifier { return certificates; } - private boolean validateRequirements(int localBindingType, Bundle requirements) { - if (requirements.size() != 1) { - debugVerboseLog("Requirements does not contain exactly 1 key."); + /** + * Check if the {@code localBindingType} is supported and if the {@code requirements} contains + * the required parameter for the given {@code @LocalBindingType}. + */ + private boolean validateAttestationParameters( + @LocalBindingType int localBindingType, @NonNull Bundle requirements) { + if (localBindingType != TYPE_PUBLIC_KEY && localBindingType != TYPE_CHALLENGE) { + debugVerboseLog("Binding type is not supported: " + localBindingType); return false; } - if (localBindingType != TYPE_PUBLIC_KEY && localBindingType != TYPE_CHALLENGE) { - debugVerboseLog("Binding type is not supported: " + localBindingType); + if (requirements.size() != 1) { + debugVerboseLog("Requirements does not contain exactly 1 key."); return false; } @@ -213,29 +238,25 @@ class AttestationVerificationPeerDeviceVerifier { return true; } - private boolean validateCertificateChain(List<X509Certificate> certificates) { + private void validateCertificateChain(List<X509Certificate> certificates) + throws CertificateException, CertPathValidatorException, + InvalidAlgorithmParameterException { if (certificates.size() < 2) { debugVerboseLog("Certificate chain less than 2 in size."); - return false; + throw new CertificateException("Certificate chain less than 2 in size."); } - try { - CertPath certificatePath = mCertificateFactory.generateCertPath(certificates); - PKIXParameters validationParams = new PKIXParameters(mTrustAnchors); - if (mRevocationEnabled) { - // Checks Revocation Status List based on - // https://developer.android.com/training/articles/security-key-attestation#certificate_status - PKIXCertPathChecker checker = new AndroidRevocationStatusListChecker(); - validationParams.addCertPathChecker(checker); - } - // Do not use built-in revocation status checker. - validationParams.setRevocationEnabled(false); - mCertPathValidator.validate(certificatePath, validationParams); - } catch (Throwable t) { - debugVerboseLog("Invalid certificate chain.", t); - return false; + CertPath certificatePath = mCertificateFactory.generateCertPath(certificates); + PKIXParameters validationParams = new PKIXParameters(mTrustAnchors); + if (mRevocationEnabled) { + // Checks Revocation Status List based on + // https://developer.android.com/training/articles/security-key-attestation#certificate_status + PKIXCertPathChecker checker = new AndroidRevocationStatusListChecker(); + validationParams.addCertPathChecker(checker); } - return true; + // Do not use built-in revocation status checker. + validationParams.setRevocationEnabled(false); + mCertPathValidator.validate(certificatePath, validationParams); } private Set<TrustAnchor> getTrustAnchors() throws CertPathValidatorException { @@ -267,18 +288,44 @@ class AttestationVerificationPeerDeviceVerifier { R.array.vendor_required_attestation_certificates); } - private boolean checkCertificateAttributes( - X509Certificate leafCertificate, int localBindingType, Bundle requirements) { - AndroidKeystoreAttestationVerificationAttributes attestationAttributes; - try { - attestationAttributes = - AndroidKeystoreAttestationVerificationAttributes.fromCertificate( - leafCertificate); - } catch (Throwable t) { - debugVerboseLog("Could not get ParsedAttestationAttributes from Certificate.", t); - return false; + private boolean checkLocalBindingRequirements( + @NonNull X509Certificate leafCertificate, + @NonNull AndroidKeystoreAttestationVerificationAttributes attestationAttributes, + @LocalBindingType int localBindingType, + @NonNull Bundle requirements) { + switch (localBindingType) { + case TYPE_PUBLIC_KEY: + // Verify leaf public key matches provided public key. + final boolean publicKeyMatches = checkPublicKey( + leafCertificate, requirements.getByteArray(PARAM_PUBLIC_KEY)); + if (!publicKeyMatches) { + debugVerboseLog( + "Provided public key does not match leaf certificate public key."); + return false; + } + break; + + case TYPE_CHALLENGE: + // Verify challenge matches provided challenge. + final boolean attestationChallengeMatches = checkAttestationChallenge( + attestationAttributes, requirements.getByteArray(PARAM_CHALLENGE)); + if (!attestationChallengeMatches) { + debugVerboseLog( + "Provided challenge does not match leaf certificate challenge."); + return false; + } + break; + + default: + throw new IllegalArgumentException("Unsupported local binding type " + + localBindingTypeToString(localBindingType)); } + return true; + } + + private boolean checkAttestationForPeerDeviceProfile( + @NonNull AndroidKeystoreAttestationVerificationAttributes attestationAttributes) { // Checks for support of Keymaster 4. if (attestationAttributes.getAttestationVersion() < 3) { debugVerboseLog("Attestation version is not at least 3 (Keymaster 4)."); @@ -344,23 +391,20 @@ class AttestationVerificationPeerDeviceVerifier { return false; } - // Verify leaf public key matches provided public key. - if (localBindingType == TYPE_PUBLIC_KEY - && !Arrays.equals(requirements.getByteArray(PARAM_PUBLIC_KEY), - leafCertificate.getPublicKey().getEncoded())) { - debugVerboseLog("Provided public key does not match leaf certificate public key."); - return false; - } + return true; + } - // Verify challenge matches provided challenge. - if (localBindingType == TYPE_CHALLENGE - && !Arrays.equals(requirements.getByteArray(PARAM_CHALLENGE), - attestationAttributes.getAttestationChallenge().toByteArray())) { - debugVerboseLog("Provided challenge does not match leaf certificate challenge."); - return false; - } + private boolean checkPublicKey( + @NonNull Certificate certificate, @NonNull byte[] expectedPublicKey) { + final byte[] publicKey = certificate.getPublicKey().getEncoded(); + return Arrays.equals(publicKey, expectedPublicKey); + } - return true; + private boolean checkAttestationChallenge( + @NonNull AndroidKeystoreAttestationVerificationAttributes attestationAttributes, + @NonNull byte[] expectedChallenge) { + final byte[] challenge = attestationAttributes.getAttestationChallenge().toByteArray(); + return Arrays.equals(challenge, expectedChallenge); } /** @@ -507,4 +551,16 @@ class AttestationVerificationPeerDeviceVerifier { R.string.vendor_required_attestation_revocation_list_url); } } + + private static void debugVerboseLog(String str, Throwable t) { + if (DEBUG) { + Slog.v(TAG, str, t); + } + } + + private static void debugVerboseLog(String str) { + if (DEBUG) { + Slog.v(TAG, str); + } + } } diff --git a/services/core/java/com/android/server/slice/SliceManagerService.java b/services/core/java/com/android/server/slice/SliceManagerService.java index e3dcfd0c89c0..881bdbd3bc6a 100644 --- a/services/core/java/com/android/server/slice/SliceManagerService.java +++ b/services/core/java/com/android/server/slice/SliceManagerService.java @@ -65,7 +65,6 @@ import com.android.internal.app.AssistUtils; import com.android.server.LocalServices; import com.android.server.ServiceThread; import com.android.server.SystemService; -import com.android.server.SystemService.TargetUser; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -226,12 +225,18 @@ public class SliceManagerService extends ISliceManager.Stub { } @Override - public int checkSlicePermission(Uri uri, String callingPkg, String pkg, int pid, int uid, + public int checkSlicePermission(Uri uri, String callingPkg, int pid, int uid, String[] autoGrantPermissions) { + return checkSlicePermissionInternal(uri, callingPkg, null /* pkg */, pid, uid, + autoGrantPermissions); + } + + private int checkSlicePermissionInternal(Uri uri, String callingPkg, String pkg, int pid, + int uid, String[] autoGrantPermissions) { int userId = UserHandle.getUserId(uid); if (pkg == null) { for (String p : mContext.getPackageManager().getPackagesForUid(uid)) { - if (checkSlicePermission(uri, callingPkg, p, pid, uid, autoGrantPermissions) + if (checkSlicePermissionInternal(uri, callingPkg, p, pid, uid, autoGrantPermissions) == PERMISSION_GRANTED) { return PERMISSION_GRANTED; } @@ -395,7 +400,8 @@ public class SliceManagerService extends ISliceManager.Stub { } protected int checkAccess(String pkg, Uri uri, int uid, int pid) { - return checkSlicePermission(uri, null, pkg, pid, uid, null); + return checkSlicePermissionInternal(uri, null /* callingPkg */, pkg, pid, uid, + null /* autoGrantPermissions */); } private String getProviderPkg(Uri uri, int user) { @@ -404,7 +410,7 @@ public class SliceManagerService extends ISliceManager.Stub { String providerName = getUriWithoutUserId(uri).getAuthority(); ProviderInfo provider = mContext.getPackageManager().resolveContentProviderAsUser( providerName, 0, getUserIdFromUri(uri, user)); - return provider.packageName; + return provider == null ? null : provider.packageName; } finally { Binder.restoreCallingIdentity(ident); } @@ -629,7 +635,7 @@ public class SliceManagerService extends ISliceManager.Stub { .scheme(ContentResolver.SCHEME_CONTENT) .authority(authority) .build(), 0); - return mPermissions.getAllPackagesGranted(pkg); + return pkg == null ? new String[0] : mPermissions.getAllPackagesGranted(pkg); } /** diff --git a/services/core/java/com/android/server/tv/TvInputHal.java b/services/core/java/com/android/server/tv/TvInputHal.java index 07725038255e..b6ab35169fc4 100644 --- a/services/core/java/com/android/server/tv/TvInputHal.java +++ b/services/core/java/com/android/server/tv/TvInputHal.java @@ -155,8 +155,6 @@ final class TvInputHal implements Handler.Callback { // Handler.Callback implementation - private final Queue<Message> mPendingMessageQueue = new LinkedList<>(); - @Override public boolean handleMessage(Message msg) { switch (msg.what) { diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java index f57a852fe8c5..98dfb009e4ef 100755 --- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java +++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java @@ -69,7 +69,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Iterator; -import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -89,7 +88,7 @@ class TvInputHardwareManager implements TvInputHal.Callback { private final TvInputHal mHal = new TvInputHal(this); private final SparseArray<Connection> mConnections = new SparseArray<>(); private final List<TvInputHardwareInfo> mHardwareList = new ArrayList<>(); - private final List<HdmiDeviceInfo> mHdmiDeviceList = new LinkedList<>(); + private final List<HdmiDeviceInfo> mHdmiDeviceList = new ArrayList<>(); /* A map from a device ID to the matching TV input ID. */ private final SparseArray<String> mHardwareInputIdMap = new SparseArray<>(); /* A map from a HDMI logical address to the matching TV input ID. */ @@ -112,9 +111,9 @@ class TvInputHardwareManager implements TvInputHal.Callback { private int mCurrentMaxIndex = 0; private final SparseBooleanArray mHdmiStateMap = new SparseBooleanArray(); - private final List<Message> mPendingHdmiDeviceEvents = new LinkedList<>(); + private final List<Message> mPendingHdmiDeviceEvents = new ArrayList<>(); - private final List<Message> mPendingTvinputInfoEvents = new LinkedList<>(); + private final List<Message> mPendingTvinputInfoEvents = new ArrayList<>(); // Calls to mListener should happen here. private final Handler mHandler = new ListenerHandler(); @@ -234,11 +233,7 @@ class TvInputHardwareManager implements TvInputHal.Callback { } else { Message msg = mHandler.obtainMessage(ListenerHandler.TVINPUT_INFO_ADDED, deviceId, cableConnectionStatus, connection); - for (Iterator<Message> it = mPendingTvinputInfoEvents.iterator(); it.hasNext();) { - if (it.next().arg1 == deviceId) { - it.remove(); - } - } + mPendingTvinputInfoEvents.removeIf(message -> message.arg1 == deviceId); mPendingTvinputInfoEvents.add(msg); } ITvInputHardwareCallback callback = connection.getCallbackLocked(); diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java index 7f84f61a91ff..3b8677d70be2 100644 --- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java +++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java @@ -68,6 +68,7 @@ import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem; import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_METRICS; import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; +import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_RECENTS_ANIM; import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_TIMEOUT; import static com.android.server.wm.EventLogTags.WM_ACTIVITY_LAUNCH_TIME; @@ -102,6 +103,7 @@ import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.MetricsLogger; import com.android.internal.util.FrameworkStatsLog; +import com.android.internal.util.LatencyTracker; import com.android.internal.util.function.pooled.PooledLambda; import com.android.server.FgThread; import com.android.server.LocalServices; @@ -771,6 +773,12 @@ class ActivityMetricsLogger { info.mReason = activityToReason.valueAt(index); info.mLoggedTransitionStarting = true; if (info.mIsDrawn) { + if (info.mReason == APP_TRANSITION_RECENTS_ANIM) { + final LatencyTracker latencyTracker = r.mWmService.mLatencyTracker; + final int duration = info.mSourceEventDelayMs + info.mCurrentTransitionDelayMs; + mLoggerHandler.post(() -> latencyTracker.logAction( + LatencyTracker.ACTION_START_RECENTS_ANIMATION, duration)); + } done(false /* abort */, info, "notifyTransitionStarting drawn", timestampNs); } } diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 1956cee11f90..c73cdc303730 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -5467,7 +5467,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A wasStopped, this); mAppStopped = false; // Allow the window to turn the screen on once the app is resumed again. - setCurrentLaunchCanTurnScreenOn(true); + if (mAtmService.getActivityStartController().isInExecution()) { + setCurrentLaunchCanTurnScreenOn(true); + } + if (!wasStopped) { destroySurfaces(true /*cleanupOnResume*/); } diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java index 72408b67de41..9771b347cfb1 100644 --- a/services/core/java/com/android/server/wm/ActivityStartController.java +++ b/services/core/java/com/android/server/wm/ActivityStartController.java @@ -90,6 +90,8 @@ public class ActivityStartController { boolean mCheckedForSetup = false; + private boolean mInExecution = false; + /** * TODO(b/64750076): Capture information necessary for dump and * {@link #postStartActivityProcessingForLastStarter} rather than keeping the entire object @@ -123,7 +125,15 @@ public class ActivityStartController { return mFactory.obtain().setIntent(intent).setReason(reason); } + void onExecutionStarted(ActivityStarter starter) { + mInExecution = true; + } + + boolean isInExecution() { + return mInExecution; + } void onExecutionComplete(ActivityStarter starter) { + mInExecution = false; if (mLastStarter == null) { mLastStarter = mFactory.obtain(); } diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 75d462131aae..5438c92a1d86 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -633,6 +633,8 @@ class ActivityStarter { */ int execute() { try { + onExecutionStarted(); + // Refuse possible leaked file descriptors if (mRequest.intent != null && mRequest.intent.hasFileDescriptors()) { throw new IllegalArgumentException("File descriptors passed in Intent"); @@ -1247,6 +1249,10 @@ class ActivityStarter { mController.onExecutionComplete(this); } + private void onExecutionStarted() { + mController.onExecutionStarted(this); + } + private boolean isHomeApp(int uid, @Nullable String packageName) { if (mService.mHomeProcess != null) { // Fast check diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java index 68a09a6d4b9b..4ad960816e55 100644 --- a/services/core/java/com/android/server/wm/AppTransition.java +++ b/services/core/java/com/android/server/wm/AppTransition.java @@ -281,13 +281,6 @@ public class AppTransition implements Dump { fetchAppTransitionSpecsFromFuture(); } - void abort() { - if (mRemoteAnimationController != null) { - mRemoteAnimationController.cancelAnimation("aborted"); - } - clear(); - } - boolean isRunning() { return mAppTransitionState == APP_STATE_RUNNING; } diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java index cefc8717ed01..6f13f86c5bdf 100644 --- a/services/core/java/com/android/server/wm/AppTransitionController.java +++ b/services/core/java/com/android/server/wm/AppTransitionController.java @@ -96,8 +96,8 @@ import com.android.internal.protolog.common.ProtoLog; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.ArrayDeque; import java.util.ArrayList; -import java.util.LinkedList; import java.util.function.Consumer; import java.util.function.Predicate; @@ -854,7 +854,7 @@ public class AppTransitionController { boolean visible) { // The candidates of animation targets, which might be able to promote to higher level. - final LinkedList<WindowContainer> candidates = new LinkedList<>(); + final ArrayDeque<WindowContainer> candidates = new ArrayDeque<>(); final ArraySet<ActivityRecord> apps = visible ? openingApps : closingApps; for (int i = 0; i < apps.size(); ++i) { final ActivityRecord app = apps.valueAt(i); diff --git a/services/core/java/com/android/server/wm/BLASTSyncEngine.java b/services/core/java/com/android/server/wm/BLASTSyncEngine.java index 3f300bce54c4..67eb9c8911a7 100644 --- a/services/core/java/com/android/server/wm/BLASTSyncEngine.java +++ b/services/core/java/com/android/server/wm/BLASTSyncEngine.java @@ -221,12 +221,18 @@ class BLASTSyncEngine { private void onTimeout() { if (!mActiveSyncs.contains(mSyncId)) return; + boolean allFinished = true; for (int i = mRootMembers.size() - 1; i >= 0; --i) { final WindowContainer<?> wc = mRootMembers.valueAt(i); if (!wc.isSyncFinished()) { + allFinished = false; Slog.i(TAG, "Unfinished container: " + wc); } } + if (allFinished && !mReady) { + Slog.w(TAG, "Sync group " + mSyncId + " timed-out because not ready. If you see " + + "this, please file a bug."); + } finishNow(); } } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 01d1614610a2..752bc2286123 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -1579,8 +1579,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp mAtmService.getTaskChangeNotificationController() .notifyTaskRequestedOrientationChanged(task.mTaskId, orientation); } - // Currently there is no use case from non-activity. - if (handleTopActivityLaunchingInDifferentOrientation(r, true /* checkOpening */)) { + // The orientation source may not be the top if it uses SCREEN_ORIENTATION_BEHIND. + final ActivityRecord topCandidate = !r.mVisibleRequested ? topRunningActivity() : r; + if (handleTopActivityLaunchingInDifferentOrientation( + topCandidate, r, true /* checkOpening */)) { // Display orientation should be deferred until the top fixed rotation is finished. return false; } @@ -1597,7 +1599,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp /** * Returns a valid rotation if the activity can use different orientation than the display. - * Otherwise {@link #ROTATION_UNDEFINED}. + * Otherwise {@link android.app.WindowConfiguration#ROTATION_UNDEFINED}. */ @Rotation int rotationForActivityInDifferentOrientation(@NonNull ActivityRecord r) { @@ -1607,6 +1609,15 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp if (!WindowManagerService.ENABLE_FIXED_ROTATION_TRANSFORM) { return ROTATION_UNDEFINED; } + if (r.mOrientation == ActivityInfo.SCREEN_ORIENTATION_BEHIND) { + final ActivityRecord nextCandidate = getActivity( + a -> a.mOrientation != SCREEN_ORIENTATION_UNSET + && a.mOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND, + r, false /* includeBoundary */, true /* traverseTopToBottom */); + if (nextCandidate != null) { + r = nextCandidate; + } + } if (r.inMultiWindowMode() || r.getRequestedConfigurationOrientation(true /* forDisplay */) == getConfiguration().orientation) { return ROTATION_UNDEFINED; @@ -1620,18 +1631,25 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp return rotation; } + boolean handleTopActivityLaunchingInDifferentOrientation(@NonNull ActivityRecord r, + boolean checkOpening) { + return handleTopActivityLaunchingInDifferentOrientation(r, r, checkOpening); + } + /** * We need to keep display rotation fixed for a while when the activity in different orientation * is launching until the launch animation is done to avoid showing the previous activity * inadvertently in a wrong orientation. * * @param r The launching activity which may change display orientation. + * @param orientationSrc It may be different from {@param r} if the launching activity uses + * "behind" orientation. * @param checkOpening Whether to check if the activity is animating by transition. Set to * {@code true} if the caller is not sure whether the activity is launching. * @return {@code true} if the fixed rotation is started. */ - boolean handleTopActivityLaunchingInDifferentOrientation(@NonNull ActivityRecord r, - boolean checkOpening) { + private boolean handleTopActivityLaunchingInDifferentOrientation(@NonNull ActivityRecord r, + @NonNull ActivityRecord orientationSrc, boolean checkOpening) { if (!WindowManagerService.ENABLE_FIXED_ROTATION_TRANSFORM) { return false; } @@ -1680,7 +1698,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp // animation is not running (it may be swiping to home). return false; } - final int rotation = rotationForActivityInDifferentOrientation(r); + final int rotation = rotationForActivityInDifferentOrientation(orientationSrc); if (rotation == ROTATION_UNDEFINED) { // The display rotation won't be changed by current top activity. The client side // adjustments of previous rotated activity should be cleared earlier. Otherwise if @@ -2001,7 +2019,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp ProtoLog.v(WM_DEBUG_ORIENTATION, "Set mOrientationChanging of %s", w); w.setOrientationChanging(true); } - w.mReportOrientationChanged = true; }, true /* traverseTopToBottom */); for (int i = mWmService.mRotationWatchers.size() - 1; i >= 0; i--) { @@ -4487,8 +4504,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp boolean wallpaperEnabled = mWmService.mContext.getResources().getBoolean( com.android.internal.R.bool.config_enableWallpaperService) && mWmService.mContext.getResources().getBoolean( - com.android.internal.R.bool.config_checkWallpaperAtBoot) - && !mWmService.mOnlyCore; + com.android.internal.R.bool.config_checkWallpaperAtBoot); final boolean haveBootMsg = drawnWindowTypes.get(TYPE_BOOT_PROGRESS); final boolean haveApp = drawnWindowTypes.get(TYPE_BASE_APPLICATION); @@ -5281,11 +5297,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } } - void cancelAppTransition() { - if (!mAppTransition.isTransitionSet() || mAppTransition.isRunning()) return; - mAppTransition.abort(); - } - /** * Update pendingLayoutChanges after app transition has finished. */ diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 22714c6f5593..4fc31f8cd182 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -1977,23 +1977,23 @@ class RootWindowContainer extends WindowContainer<DisplayContent> void moveActivityToPinnedRootTask(@NonNull ActivityRecord r, @Nullable ActivityRecord launchIntoPipHostActivity, String reason) { - mService.deferWindowLayout(); final TaskDisplayArea taskDisplayArea = r.getDisplayArea(); + final Task task = r.getTask(); + final Task rootTask; - try { - final Task task = r.getTask(); - - // Create a transition now to collect the current pinned Task dismiss. Only do the - // create here as the Task (trigger) to enter PIP is not ready yet. - final TransitionController transitionController = task.mTransitionController; - Transition newTransition = null; - if (transitionController.isCollecting()) { - transitionController.setReady(task, false /* ready */); - } else if (transitionController.getTransitionPlayer() != null) { - newTransition = transitionController.createTransition(TRANSIT_PIP); - } + Transition newTransition = null; + // Create a transition now to collect the current pinned Task dismiss. Only do the + // create here as the Task (trigger) to enter PIP is not ready yet. + final TransitionController transitionController = task.mTransitionController; + if (!transitionController.isCollecting() + && transitionController.getTransitionPlayer() != null) { + newTransition = transitionController.createTransition(TRANSIT_PIP); + } + transitionController.deferTransitionReady(); + mService.deferWindowLayout(); + try { // This will change the root pinned task's windowing mode to its original mode, ensuring // we only have one root task that is in pinned mode. final Task rootPinnedTask = taskDisplayArea.getRootPinnedTask(); @@ -2008,7 +2008,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent> final TaskFragment organizedTf = r.getOrganizedTaskFragment(); final boolean singleActivity = task.getNonFinishingActivityCount() == 1; - final Task rootTask; if (singleActivity) { rootTask = task; @@ -2074,6 +2073,9 @@ class RootWindowContainer extends WindowContainer<DisplayContent> oldTopActivity.mRequestForceTransition = true; } } + + transitionController.collect(rootTask); + // The intermediate windowing mode to be set on the ActivityRecord later. // This needs to happen before the re-parenting, otherwise we will always set the // ActivityRecord to be fullscreen. @@ -2084,13 +2086,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent> rootTask.reparent(taskDisplayArea, true /* onTop */); } - // The new PIP Task is ready, start the transition before updating the windowing mode. - if (newTransition != null) { - transitionController.requestStartTransition(newTransition, rootTask, - null /* remoteTransition */, null /* displayChange */); - } - transitionController.collect(rootTask); - // Defer the windowing mode change until after the transition to prevent the activity // from doing work and changing the activity visuals while animating // TODO(task-org): Figure-out more structured way to do this long term. @@ -2124,9 +2119,23 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } } finally { mService.continueWindowLayout(); + try { + ensureActivitiesVisible(null, 0, false /* preserveWindows */); + } finally { + transitionController.continueTransitionReady(); + } + } + + if (newTransition != null) { + // Request at end since we want task-organizer events from ensureActivitiesVisible + // to be recognized. + transitionController.requestStartTransition(newTransition, rootTask, + null /* remoteTransition */, null /* displayChange */); + // A new transition was created just for this operations. Since the operation is + // complete, mark it as ready. + newTransition.setReady(rootTask, true /* ready */); } - ensureActivitiesVisible(null, 0, false /* preserveWindows */); resumeFocusedTasksTopActivities(); notifyActivityPipModeChanged(r.getTask(), r); diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java index 7a7bf1f877b9..d7691f65f580 100644 --- a/services/core/java/com/android/server/wm/TaskDisplayArea.java +++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java @@ -422,8 +422,10 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { // wasContained} restricts the preferred root task is set only when moving an existing // root task to top instead of adding a new root task that may be too early (e.g. in the // middle of launching or reparenting). - if (moveToTop && child.isFocusableAndVisible()) { - mPreferredTopFocusableRootTask = child; + final boolean isTopFocusableTask = moveToTop && child.isTopActivityFocusable(); + if (isTopFocusableTask) { + mPreferredTopFocusableRootTask = + child.shouldBeVisible(null /* starting */) ? child : null; } else if (mPreferredTopFocusableRootTask == child) { mPreferredTopFocusableRootTask = null; } diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java index 9bf988f16090..7a2d4f955beb 100644 --- a/services/core/java/com/android/server/wm/TaskOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java @@ -54,10 +54,10 @@ import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.ArrayUtils; import java.io.PrintWriter; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedList; import java.util.List; import java.util.WeakHashMap; import java.util.function.Consumer; @@ -319,13 +319,13 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { private final WindowManagerGlobalLock mGlobalLock; // List of task organizers by priority - private final LinkedList<ITaskOrganizer> mTaskOrganizers = new LinkedList<>(); + private final ArrayDeque<ITaskOrganizer> mTaskOrganizers = new ArrayDeque<>(); private final HashMap<IBinder, TaskOrganizerState> mTaskOrganizerStates = new HashMap<>(); private final WeakHashMap<Task, RunningTaskInfo> mLastSentTaskInfos = new WeakHashMap<>(); // Pending task events due to layout deferred. private final ArrayList<PendingTaskEvent> mPendingTaskEvents = new ArrayList<>(); // Set of organized tasks (by taskId) that dispatch back pressed to their organizers - private final HashSet<Integer> mInterceptBackPressedOnRootTasks = new HashSet(); + private final HashSet<Integer> mInterceptBackPressedOnRootTasks = new HashSet<>(); private RunningTaskInfo mTmpTaskInfo; private Consumer<Runnable> mDeferTaskOrgCallbacksConsumer; diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index f6f9020555d8..342a0e52952c 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -52,6 +52,7 @@ import static android.window.TransitionInfo.FLAG_SHOW_WALLPAPER; import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT; import static android.window.TransitionInfo.FLAG_TRANSLUCENT; +import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_RECENTS_ANIM; import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_SPLASH_SCREEN; import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_WINDOWS_DRAWN; @@ -685,8 +686,6 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe handleNonAppWindowsInTransition(dc, mType, mFlags); - reportStartReasonsToLogger(); - // The callback is only populated for custom activity-level client animations sendRemoteCallback(mClientAnimationStartCallback); @@ -728,6 +727,9 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe for (int i = mParticipants.size() - 1; i >= 0; --i) { final WindowContainer wc = mParticipants.valueAt(i); if (wc.asWindowToken() == null || !wc.isVisibleRequested()) continue; + // don't include transient launches, though, since those are only temporarily visible. + if (mTransientLaunches != null && wc.asActivityRecord() != null + && mTransientLaunches.containsKey(wc.asActivityRecord())) continue; mVisibleAtTransitionEndTokens.add(wc.asWindowToken()); } @@ -775,6 +777,8 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe } mSyncId = -1; mOverrideOptions = null; + + reportStartReasonsToLogger(); } /** @@ -987,11 +991,15 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe for (int i = mParticipants.size() - 1; i >= 0; --i) { ActivityRecord r = mParticipants.valueAt(i).asActivityRecord(); if (r == null || !r.mVisibleRequested) continue; + int transitionReason = APP_TRANSITION_WINDOWS_DRAWN; // At this point, r is "ready", but if it's not "ALL ready" then it is probably only // ready due to starting-window. - reasons.put(r, (r.mStartingData instanceof SplashScreenStartingData - && !r.mLastAllReadyAtSync) - ? APP_TRANSITION_SPLASH_SCREEN : APP_TRANSITION_WINDOWS_DRAWN); + if (r.mStartingData instanceof SplashScreenStartingData && !r.mLastAllReadyAtSync) { + transitionReason = APP_TRANSITION_SPLASH_SCREEN; + } else if (r.isActivityTypeHomeOrRecents() && isTransientLaunch(r)) { + transitionReason = APP_TRANSITION_RECENTS_ANIM; + } + reasons.put(r, transitionReason); } mController.mAtm.mTaskSupervisor.getActivityMetricsLogger().notifyTransitionStarting( reasons); @@ -1610,6 +1618,19 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe } /** + * This transition will be considered not-ready until a corresponding call to + * {@link #continueTransitionReady} + */ + void deferTransitionReady() { + ++mReadyTracker.mDeferReadyDepth; + } + + /** This undoes one call to {@link #deferTransitionReady}. */ + void continueTransitionReady() { + --mReadyTracker.mDeferReadyDepth; + } + + /** * The transition sync mechanism has 2 parts: * 1. Whether all WM operations for a particular transition are "ready" (eg. did the app * launch or stop or get a new configuration?). @@ -1639,6 +1660,14 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe private boolean mReadyOverride = false; /** + * When non-zero, this transition is forced not-ready (even over setAllReady()). Use this + * (via deferTransitionReady/continueTransitionReady) for situations where we want to do + * bulk operations which could trigger surface-placement but the existing ready-state + * isn't known. + */ + private int mDeferReadyDepth = 0; + + /** * Adds a ready-group. Any setReady calls in this subtree will be tracked together. For * now these are only DisplayContents. */ @@ -1679,7 +1708,13 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe boolean allReady() { ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, " allReady query: used=%b " + "override=%b states=[%s]", mUsed, mReadyOverride, groupsToString()); + // If the readiness has never been touched, mUsed will be false. We never want to + // consider a transition ready if nothing has been reported on it. if (!mUsed) return false; + // If we are deferring readiness, we never report ready. This is usually temporary. + if (mDeferReadyDepth > 0) return false; + // Next check all the ready groups to see if they are ready. We can short-cut this if + // ready-override is set (which is treated as "everything is marked ready"). if (mReadyOverride) return true; for (int i = mReadyGroups.size() - 1; i >= 0; --i) { final WindowContainer wc = mReadyGroups.keyAt(i); diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java index c1c390eea932..417e6ed6a07e 100644 --- a/services/core/java/com/android/server/wm/TransitionController.java +++ b/services/core/java/com/android/server/wm/TransitionController.java @@ -455,6 +455,24 @@ class TransitionController { setReady(wc, true); } + /** @see Transition#deferTransitionReady */ + void deferTransitionReady() { + if (!isShellTransitionsEnabled()) return; + if (mCollectingTransition == null) { + throw new IllegalStateException("No collecting transition to defer readiness for."); + } + mCollectingTransition.deferTransitionReady(); + } + + /** @see Transition#continueTransitionReady */ + void continueTransitionReady() { + if (!isShellTransitionsEnabled()) return; + if (mCollectingTransition == null) { + throw new IllegalStateException("No collecting transition to defer readiness for."); + } + mCollectingTransition.continueTransitionReady(); + } + /** @see Transition#finishTransition */ void finishTransition(@NonNull IBinder token) { // It is usually a no-op but make sure that the metric consumer is removed. diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index c7bc51356c76..60188f56f5bb 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -3003,7 +3003,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< AnimationRunnerBuilder animationRunnerBuilder = new AnimationRunnerBuilder(); - if (isTaskTransitOld(transit)) { + if (isTaskTransitOld(transit) && getWindowingMode() == WINDOWING_MODE_FULLSCREEN) { animationRunnerBuilder.setTaskBackgroundColor(getTaskAnimationBackgroundColor()); // TODO: Remove when we migrate to shell (b/202383002) if (mWmService.mTaskTransitionSpec != null) { diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index c37c9cb72ec5..b45961953dcf 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -1052,17 +1052,11 @@ public class WindowManagerService extends IWindowManager.Stub // logical displays. final PossibleDisplayInfoMapper mPossibleDisplayInfoMapper; - // If true, only the core apps and services are being launched because the device - // is in a special boot mode, such as being encrypted or waiting for a decryption password. - // For example, when this flag is true, there will be no wallpaper service. - final boolean mOnlyCore; - static WindowManagerThreadPriorityBooster sThreadPriorityBooster = new WindowManagerThreadPriorityBooster(); Function<SurfaceSession, SurfaceControl.Builder> mSurfaceControlFactory; Supplier<SurfaceControl.Transaction> mTransactionFactory; - final Supplier<Surface> mSurfaceFactory; private final SurfaceControl.Transaction mTransaction; @@ -1142,11 +1136,10 @@ public class WindowManagerService extends IWindowManager.Stub } public static WindowManagerService main(final Context context, final InputManagerService im, - final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy, + final boolean showBootMsgs, WindowManagerPolicy policy, ActivityTaskManagerService atm) { - return main(context, im, showBootMsgs, onlyCore, policy, atm, - new DisplayWindowSettingsProvider(), SurfaceControl.Transaction::new, Surface::new, - SurfaceControl.Builder::new); + return main(context, im, showBootMsgs, policy, atm, new DisplayWindowSettingsProvider(), + SurfaceControl.Transaction::new, SurfaceControl.Builder::new); } /** @@ -1155,15 +1148,14 @@ public class WindowManagerService extends IWindowManager.Stub */ @VisibleForTesting public static WindowManagerService main(final Context context, final InputManagerService im, - final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy, - ActivityTaskManagerService atm, DisplayWindowSettingsProvider - displayWindowSettingsProvider, Supplier<SurfaceControl.Transaction> transactionFactory, - Supplier<Surface> surfaceFactory, + final boolean showBootMsgs, WindowManagerPolicy policy, ActivityTaskManagerService atm, + DisplayWindowSettingsProvider displayWindowSettingsProvider, + Supplier<SurfaceControl.Transaction> transactionFactory, Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) { final WindowManagerService[] wms = new WindowManagerService[1]; DisplayThread.getHandler().runWithScissors(() -> - wms[0] = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy, - atm, displayWindowSettingsProvider, transactionFactory, surfaceFactory, + wms[0] = new WindowManagerService(context, im, showBootMsgs, policy, atm, + displayWindowSettingsProvider, transactionFactory, surfaceControlFactory), 0); return wms[0]; } @@ -1185,10 +1177,9 @@ public class WindowManagerService extends IWindowManager.Stub } private WindowManagerService(Context context, InputManagerService inputManager, - boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy, - ActivityTaskManagerService atm, DisplayWindowSettingsProvider - displayWindowSettingsProvider, Supplier<SurfaceControl.Transaction> transactionFactory, - Supplier<Surface> surfaceFactory, + boolean showBootMsgs, WindowManagerPolicy policy, ActivityTaskManagerService atm, + DisplayWindowSettingsProvider displayWindowSettingsProvider, + Supplier<SurfaceControl.Transaction> transactionFactory, Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) { installLock(this, INDEX_WINDOW); mGlobalLock = atm.getGlobalLock(); @@ -1196,7 +1187,6 @@ public class WindowManagerService extends IWindowManager.Stub mContext = context; mIsPc = mContext.getPackageManager().hasSystemFeature(FEATURE_PC); mAllowBootMessages = showBootMsgs; - mOnlyCore = onlyCore; mLimitedAlphaCompositing = context.getResources().getBoolean( com.android.internal.R.bool.config_sf_limitedAlpha); mHasPermanentDpad = context.getResources().getBoolean( @@ -1228,7 +1218,6 @@ public class WindowManagerService extends IWindowManager.Stub mSurfaceControlFactory = surfaceControlFactory; mTransactionFactory = transactionFactory; - mSurfaceFactory = surfaceFactory; mTransaction = mTransactionFactory.get(); mPolicy = policy; @@ -3654,8 +3643,8 @@ public class WindowManagerService extends IWindowManager.Stub synchronized (mGlobalLock) { ProtoLog.i(WM_DEBUG_BOOT, "performEnableScreen: mDisplayEnabled=%b" + " mForceDisplayEnabled=%b" + " mShowingBootMessages=%b" - + " mSystemBooted=%b mOnlyCore=%b. %s", mDisplayEnabled, - mForceDisplayEnabled, mShowingBootMessages, mSystemBooted, mOnlyCore, + + " mSystemBooted=%b. %s", mDisplayEnabled, + mForceDisplayEnabled, mShowingBootMessages, mSystemBooted, new RuntimeException("here").fillInStackTrace()); if (mDisplayEnabled) { return; @@ -3703,11 +3692,12 @@ public class WindowManagerService extends IWindowManager.Stub } try { - IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger"); + // TODO(b/221898546): remove the following and convert to jni + IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlingerAIDL"); if (surfaceFlinger != null) { ProtoLog.i(WM_ERROR, "******* TELLING SURFACE FLINGER WE ARE BOOTED!"); Parcel data = Parcel.obtain(); - data.writeInterfaceToken("android.ui.ISurfaceComposer"); + data.writeInterfaceToken("android.gui.ISurfaceComposer"); surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED data, null, 0); data.recycle(); diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java index 67f7ff701981..27d60413acc2 100644 --- a/services/core/java/com/android/server/wm/WindowOrganizerController.java +++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java @@ -411,11 +411,13 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub } if (transition != null) transition.collect(wc); - if (finishTransition != null) { - // Deal with edge-cases in recents where it pretends to finish itself. - if ((entry.getValue().getChangeMask() - & WindowContainerTransaction.Change.CHANGE_FORCE_NO_PIP) != 0) { + if ((entry.getValue().getChangeMask() + & WindowContainerTransaction.Change.CHANGE_FORCE_NO_PIP) != 0) { + // Disable entering pip (eg. when recents pretends to finish itself) + if (finishTransition != null) { finishTransition.setCanPipOnFinish(false /* canPipOnFinish */); + } else if (transition != null) { + transition.setCanPipOnFinish(false /* canPipOnFinish */); } } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 238f96ffd1e1..a9e66a178318 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -616,11 +616,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP int mLastVisibleLayoutRotation = -1; /** - * Set when we need to report the orientation change to client to trigger a relayout. - */ - boolean mReportOrientationChanged; - - /** * How long we last kept the screen frozen. */ int mLastFreezeDuration; @@ -1541,13 +1536,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP || configChanged || insetsChanged || dragResizingChanged - || mReportOrientationChanged || shouldSendRedrawForSync()) { ProtoLog.v(WM_DEBUG_RESIZE, - "Resize reasons for w=%s: %s configChanged=%b " - + "dragResizingChanged=%b reportOrientationChanged=%b", + "Resize reasons for w=%s: %s configChanged=%b dragResizingChanged=%b", this, mWindowFrames.getInsetsChangedInfo(), - configChanged, dragResizingChanged, mReportOrientationChanged); + configChanged, dragResizingChanged); if (insetsChanged) { mWindowFrames.setInsetsChanged(false); @@ -3592,10 +3585,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP mAnimatingExit = false; ProtoLog.d(WM_DEBUG_ANIM, "Clear animatingExit: reason=destroySurface win=%s", this); - // Clear the flag so the buffer requested for the next new surface won't be dropped by - // mistaking the surface size needs to update. - mReportOrientationChanged = false; - if (useBLASTSync()) { immediatelyNotifyBlastSync(); } @@ -3914,12 +3903,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP ProtoLog.i(WM_DEBUG_ORIENTATION, "Resizing %s WITH DRAW PENDING", this); } - final boolean reportOrientation = mReportOrientationChanged; // Always reset these states first, so if {@link IWindow#resized} fails, this // window won't be added to {@link WindowManagerService#mResizingWindows} and set // {@link #mOrientationChanging} to true again by {@link #updateResizingWindowIfNeeded} // that may cause WINDOW_FREEZE_TIMEOUT because resizing the client keeps failing. - mReportOrientationChanged = false; mDragResizingChangeReported = true; mWindowFrames.clearReportResizeHints(); @@ -3928,7 +3915,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP final boolean syncRedraw = shouldSendRedrawForSync(); final boolean reportDraw = syncRedraw || drawPending; final boolean isDragResizeChanged = isDragResizeChanged(); - final boolean forceRelayout = syncRedraw || reportOrientation || isDragResizeChanged; + final boolean forceRelayout = syncRedraw || isDragResizeChanged; final DisplayContent displayContent = getDisplayContent(); final boolean alwaysConsumeSystemBars = displayContent.getDisplayPolicy().areSystemBarsForcedShownLw(); @@ -3955,7 +3942,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP mClient.resized(mClientWindowFrames, reportDraw, mLastReportedConfiguration, getCompatInsetsState(), forceRelayout, alwaysConsumeSystemBars, displayId, mSyncSeqId, resizeMode); - if (drawPending && reportOrientation && mOrientationChanging) { + if (drawPending && mOrientationChanging) { mOrientationChangeRedrawRequestTime = SystemClock.elapsedRealtime(); ProtoLog.v(WM_DEBUG_ORIENTATION, "Requested redraw for orientation change: %s", this); @@ -4380,12 +4367,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP + " mDestroying=" + mDestroying + " mRemoved=" + mRemoved); } - if (getOrientationChanging() || mAppFreezing || mReportOrientationChanged) { + if (getOrientationChanging() || mAppFreezing) { pw.println(prefix + "mOrientationChanging=" + mOrientationChanging + " configOrientationChanging=" + (getLastReportedConfiguration().orientation != getConfiguration().orientation) - + " mAppFreezing=" + mAppFreezing - + " mReportOrientationChanged=" + mReportOrientationChanged); + + " mAppFreezing=" + mAppFreezing); } if (mLastFreezeDuration != 0) { pw.print(prefix + "mLastFreezeDuration="); @@ -5586,7 +5572,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP mLastSurfaceInsets.set(mAttrs.surfaceInsets); } if (surfaceSizeChanged && mWinAnimator.getShown() && !canPlayMoveAnimation() - && okToDisplay()) { + && okToDisplay() && !useBLASTSync()) { applyWithNextDraw(mSetSurfacePositionConsumer); } else { mSetSurfacePositionConsumer.accept(t); diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp index 0d49f5fffb4b..ec38f777593f 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -181,10 +181,11 @@ cc_defaults { "android.frameworks.schedulerservice@1.0", "android.frameworks.sensorservice@1.0", "android.frameworks.stats@1.0", - "android.frameworks.stats-V1-ndk", + "android.frameworks.stats-V2-ndk", "android.system.suspend.control-V1-cpp", "android.system.suspend.control.internal-cpp", "android.system.suspend-V1-ndk", + "server_configurable_flags", "service.incremental", ], diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp index 3c5ebe7c62ee..ffda8be56b3f 100644 --- a/services/core/jni/com_android_server_input_InputManagerService.cpp +++ b/services/core/jni/com_android_server_input_InputManagerService.cpp @@ -50,6 +50,7 @@ #include <nativehelper/ScopedLocalRef.h> #include <nativehelper/ScopedPrimitiveArray.h> #include <nativehelper/ScopedUtfChars.h> +#include <server_configurable_flags/get_flags.h> #include <ui/Region.h> #include <utils/Log.h> #include <utils/Looper.h> @@ -87,6 +88,13 @@ namespace android { // where the speed ranges from -7 to + 7 and is supplied by the user. static const float POINTER_SPEED_EXPONENT = 1.0f / 4; +// Category (=namespace) name for the input settings that are applied at boot time +static const char* INPUT_NATIVE_BOOT = "input_native_boot"; +/** + * Feature flag name. This flag determines which VelocityTracker strategy is used by default. + */ +static const char* VELOCITYTRACKER_STRATEGY = "velocitytracker_strategy"; + static struct { jclass clazz; jmethodID notifyConfigurationChanged; @@ -2120,8 +2128,10 @@ static void nativeReloadDeviceAliases(JNIEnv* env, jobject nativeImplObj) { static std::string dumpInputProperties() { std::string out = "Input properties:\n"; const std::string strategy = - sysprop::InputProperties::velocitytracker_strategy().value_or("default"); - out += " persist.input.velocitytracker.strategy = " + strategy + "\n"; + server_configurable_flags::GetServerConfigurableFlag(INPUT_NATIVE_BOOT, + VELOCITYTRACKER_STRATEGY, + "default"); + out += " velocitytracker_strategy (flag value) = " + strategy + "\n"; out += "\n"; return out; } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 18bffebb427c..6e0412dc18c6 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -2688,11 +2688,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final DevicePolicyData policy = getUserData(userId); if (who != null) { ActiveAdmin admin = policy.mAdminMap.get(who); - if (admin == null) { - throw new SecurityException("No active admin " + who); - } - if (admin.getUid() != uid) { - throw new SecurityException("Admin " + who + " is not owned by uid " + uid); + if (admin == null || admin.getUid() != uid) { + throw new SecurityException( + "Admin " + who + " is not active or not owned by uid " + uid); } if (isActiveAdminWithPolicyForUserLocked(admin, reqPolicy, userId)) { return admin; @@ -11732,6 +11730,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { ap = getParentOfAdminIfRequired(getOrganizationOwnedProfileOwnerLocked(caller), parent); } else { + Preconditions.checkCallAuthorization(!isFinancedDeviceOwner(caller)); ap = getParentOfAdminIfRequired(getProfileOwnerOrDeviceOwnerLocked(caller), parent); } diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index dc2b6f8d3b64..28698221a9e8 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -79,7 +79,6 @@ import android.os.storage.IStorageManager; import android.provider.DeviceConfig; import android.provider.Settings; import android.server.ServerProtoEnums; -import android.sysprop.VoldProperties; import android.system.ErrnoException; import android.system.Os; import android.text.TextUtils; @@ -238,9 +237,6 @@ public final class SystemServer implements Dumpable { private static final String TAG = "SystemServer"; - private static final String ENCRYPTING_STATE = "trigger_restart_min_framework"; - private static final String ENCRYPTED_STATE = "1"; - private static final long SLOW_DISPATCH_THRESHOLD_MS = 100; private static final long SLOW_DELIVERY_THRESHOLD_MS = 200; @@ -462,7 +458,6 @@ public final class SystemServer implements Dumpable { private DataLoaderManagerService mDataLoaderManagerService; private long mIncrementalServiceHandle = 0; - private boolean mOnlyCore; private boolean mFirstBoot; private final int mStartCount; private final boolean mRuntimeRestart; @@ -1203,16 +1198,6 @@ public final class SystemServer implements Dumpable { mSystemServiceManager.startBootPhase(t, SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY); t.traceEnd(); - // Only run "core" apps if we're encrypting the device. - String cryptState = VoldProperties.decrypt().orElse(""); - if (ENCRYPTING_STATE.equals(cryptState)) { - Slog.w(TAG, "Detected encryption in progress - only parsing core apps"); - mOnlyCore = true; - } else if (ENCRYPTED_STATE.equals(cryptState)) { - Slog.w(TAG, "Device encrypted - only parsing core apps"); - mOnlyCore = true; - } - // Start the package manager. if (!mRuntimeRestart) { FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED, @@ -1233,7 +1218,7 @@ public final class SystemServer implements Dumpable { Watchdog.getInstance().pauseWatchingCurrentThread("packagemanagermain"); Pair<PackageManagerService, IPackageManager> pmsPair = PackageManagerService.main( mSystemContext, installer, domainVerificationService, - mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore); + mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, /* onlyCore= */ false); mPackageManagerService = pmsPair.first; iPackageManager = pmsPair.second; } finally { @@ -1256,21 +1241,17 @@ public final class SystemServer implements Dumpable { } // Manages A/B OTA dexopting. This is a bootstrap service as we need it to rename // A/B artifacts after boot, before anything else might touch/need them. - // Note: this isn't needed during decryption (we don't have /data anyways). - if (!mOnlyCore) { - boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt", - false); - if (!disableOtaDexopt) { - t.traceBegin("StartOtaDexOptService"); - try { - Watchdog.getInstance().pauseWatchingCurrentThread("moveab"); - OtaDexoptService.main(mSystemContext, mPackageManagerService); - } catch (Throwable e) { - reportWtf("starting OtaDexOptService", e); - } finally { - Watchdog.getInstance().resumeWatchingCurrentThread("moveab"); - t.traceEnd(); - } + boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt", false); + if (!disableOtaDexopt) { + t.traceBegin("StartOtaDexOptService"); + try { + Watchdog.getInstance().pauseWatchingCurrentThread("moveab"); + OtaDexoptService.main(mSystemContext, mPackageManagerService); + } catch (Throwable e) { + reportWtf("starting OtaDexOptService", e); + } finally { + Watchdog.getInstance().resumeWatchingCurrentThread("moveab"); + t.traceEnd(); } } @@ -1584,7 +1565,7 @@ public final class SystemServer implements Dumpable { t.traceBegin("StartWindowManagerService"); // WMS needs sensor service ready mSystemServiceManager.startBootPhase(t, SystemService.PHASE_WAIT_FOR_SENSOR_SERVICE); - wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore, + wm = WindowManagerService.main(context, inputManager, !mFirstBoot, new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager); ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO); @@ -1758,19 +1739,16 @@ public final class SystemServer implements Dumpable { } t.traceEnd(); - - if (!mOnlyCore) { - t.traceBegin("UpdatePackagesIfNeeded"); - try { - Watchdog.getInstance().pauseWatchingCurrentThread("dexopt"); - mPackageManagerService.updatePackagesIfNeeded(); - } catch (Throwable e) { - reportWtf("update packages", e); - } finally { - Watchdog.getInstance().resumeWatchingCurrentThread("dexopt"); - } - t.traceEnd(); + t.traceBegin("UpdatePackagesIfNeeded"); + try { + Watchdog.getInstance().pauseWatchingCurrentThread("dexopt"); + mPackageManagerService.updatePackagesIfNeeded(); + } catch (Throwable e) { + reportWtf("update packages", e); + } finally { + Watchdog.getInstance().resumeWatchingCurrentThread("dexopt"); } + t.traceEnd(); t.traceBegin("PerformFstrimIfNeeded"); try { @@ -2309,13 +2287,9 @@ public final class SystemServer implements Dumpable { t.traceEnd(); // timezone.RulesManagerService will prevent a device starting up if the chain of trust - // required for safe time zone updates might be broken. RuleManagerService cannot do - // this check when mOnlyCore == true, so we don't enable the service in this case. - // This service requires that JobSchedulerService is already started when it starts. - final boolean startRulesManagerService = - !mOnlyCore && context.getResources().getBoolean( - R.bool.config_enableUpdateableTimeZoneRules); - if (startRulesManagerService) { + // required for safe time zone updates might be broken. This service requires that + // JobSchedulerService is already started when it starts. + if (context.getResources().getBoolean(R.bool.config_enableUpdateableTimeZoneRules)) { t.traceBegin("StartTimeZoneRulesManagerService"); mSystemServiceManager.startService(TIME_ZONE_RULES_MANAGER_SERVICE_CLASS); t.traceEnd(); @@ -2720,8 +2694,8 @@ public final class SystemServer implements Dumpable { t.traceBegin("MakeDisplayManagerServiceReady"); try { - // TODO: use boot phase and communicate these flags some other way - mDisplayManagerService.systemReady(safeMode, mOnlyCore); + // TODO: use boot phase and communicate this flag some other way + mDisplayManagerService.systemReady(safeMode); } catch (Throwable e) { reportWtf("making Display Manager Service ready", e); } @@ -2829,7 +2803,7 @@ public final class SystemServer implements Dumpable { // be completed before allowing 3rd party final String WEBVIEW_PREPARATION = "WebViewFactoryPreparation"; Future<?> webviewPrep = null; - if (!mOnlyCore && mWebViewUpdateService != null) { + if (mWebViewUpdateService != null) { webviewPrep = SystemServerInitThreadPool.submit(() -> { Slog.i(TAG, WEBVIEW_PREPARATION); TimingsTraceAndSlog traceLog = TimingsTraceAndSlog.newAsyncLog(); diff --git a/services/tests/PackageManagerServiceTests/appenumeration/Android.bp b/services/tests/PackageManagerServiceTests/appenumeration/Android.bp index 479ef8e5f188..cdb6324988be 100644 --- a/services/tests/PackageManagerServiceTests/appenumeration/Android.bp +++ b/services/tests/PackageManagerServiceTests/appenumeration/Android.bp @@ -30,6 +30,7 @@ android_test { "compatibility-device-util-axt", "androidx.test.runner", "truth-prebuilt", + "Harrier", ], platform_apis: true, test_suites: ["device-tests"], diff --git a/services/tests/PackageManagerServiceTests/appenumeration/AndroidManifest.xml b/services/tests/PackageManagerServiceTests/appenumeration/AndroidManifest.xml index 2039aaa20945..0395aa8a1db6 100644 --- a/services/tests/PackageManagerServiceTests/appenumeration/AndroidManifest.xml +++ b/services/tests/PackageManagerServiceTests/appenumeration/AndroidManifest.xml @@ -16,7 +16,15 @@ --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.server.pm.test.appenumeration"> + xmlns:tools="http://schemas.android.com/tools" + package="com.android.server.pm.test.appenumeration"> + + <queries> + <package android:name="com.android.appenumeration.crossuserpackagevisibility" /> + </queries> + + <!-- It's merged from Harrier library. Remove it since this test should not hold it. --> + <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" tools:node="remove" /> <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" android:targetPackage="com.android.server.pm.test.appenumeration" diff --git a/services/tests/PackageManagerServiceTests/appenumeration/AndroidTest.xml b/services/tests/PackageManagerServiceTests/appenumeration/AndroidTest.xml index 67efa142aac5..f48974a3b8e0 100644 --- a/services/tests/PackageManagerServiceTests/appenumeration/AndroidTest.xml +++ b/services/tests/PackageManagerServiceTests/appenumeration/AndroidTest.xml @@ -34,6 +34,7 @@ <option name="push" value="AppEnumerationSyncProviderTestApp.apk->/data/local/tmp/appenumerationtests/AppEnumerationSyncProviderTestApp.apk" /> <option name="push" value="AppEnumerationHasAppOpPermissionTestApp.apk->/data/local/tmp/appenumerationtests/AppEnumerationHasAppOpPermissionTestApp.apk" /> <option name="push" value="AppEnumerationSharedUserTestApp.apk->/data/local/tmp/appenumerationtests/AppEnumerationSharedUserTestApp.apk" /> + <option name="push" value="AppEnumerationCrossUserPackageVisibilityTestApp.apk->/data/local/tmp/appenumerationtests/AppEnumerationCrossUserPackageVisibilityTestApp.apk" /> </target_preparer> <option name="test-tag" value="AppEnumerationInternalTest" /> diff --git a/services/tests/PackageManagerServiceTests/appenumeration/src/com/android/server/pm/test/appenumeration/CrossUserPackageVisibilityTests.java b/services/tests/PackageManagerServiceTests/appenumeration/src/com/android/server/pm/test/appenumeration/CrossUserPackageVisibilityTests.java new file mode 100644 index 000000000000..a7ba45f0c4c2 --- /dev/null +++ b/services/tests/PackageManagerServiceTests/appenumeration/src/com/android/server/pm/test/appenumeration/CrossUserPackageVisibilityTests.java @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.pm.test.appenumeration; + +import static com.android.compatibility.common.util.ShellUtils.runShellCommand; + +import static com.google.common.truth.Truth.assertThat; + +import static org.junit.Assert.assertThrows; + +import android.app.AppGlobals; +import android.app.Instrumentation; +import android.content.Context; +import android.content.pm.IPackageManager; +import android.content.pm.KeySet; +import android.os.UserHandle; + +import androidx.test.platform.app.InstrumentationRegistry; + +import com.android.bedstead.harrier.BedsteadJUnit4; +import com.android.bedstead.harrier.DeviceState; +import com.android.bedstead.harrier.annotations.EnsureHasSecondaryUser; +import com.android.bedstead.nene.users.UserReference; + +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.File; + +/** + * Verify that app without holding the {@link android.Manifest.permission.INTERACT_ACROSS_USERS} + * can't detect the existence of another app in the different users on the device via the + * side channel attacks. + */ +@EnsureHasSecondaryUser +@RunWith(BedsteadJUnit4.class) +public class CrossUserPackageVisibilityTests { + private static final String TEST_DATA_DIR = "/data/local/tmp/appenumerationtests"; + private static final String CROSS_USER_TEST_PACKAGE_NAME = + "com.android.appenumeration.crossuserpackagevisibility"; + private static final File CROSS_USER_TEST_APK_FILE = + new File(TEST_DATA_DIR, "AppEnumerationCrossUserPackageVisibilityTestApp.apk"); + + @ClassRule + @Rule + public static final DeviceState sDeviceState = new DeviceState(); + + private Instrumentation mInstrumentation; + private IPackageManager mIPackageManager; + private Context mContext; + private UserReference mOtherUser; + + @Before + public void setup() { + mInstrumentation = InstrumentationRegistry.getInstrumentation(); + mIPackageManager = AppGlobals.getPackageManager(); + mContext = mInstrumentation.getContext(); + + // Get another user + final UserReference primaryUser = sDeviceState.primaryUser(); + if (primaryUser.id() == UserHandle.myUserId()) { + mOtherUser = sDeviceState.secondaryUser(); + } else { + mOtherUser = primaryUser; + } + + uninstallPackage(CROSS_USER_TEST_PACKAGE_NAME); + } + + @After + public void tearDown() { + uninstallPackage(CROSS_USER_TEST_PACKAGE_NAME); + } + + @Test + public void testGetSplashScreenTheme_withCrossUserId() { + final int crossUserId = UserHandle.myUserId() + 1; + assertThrows(SecurityException.class, + () -> mIPackageManager.getSplashScreenTheme( + mInstrumentation.getContext().getPackageName(), crossUserId)); + } + + @Test + public void testIsPackageSignedByKeySet_cannotDetectCrossUserPkg() throws Exception { + final KeySet keySet = mIPackageManager.getSigningKeySet(mContext.getPackageName()); + assertThrows(IllegalArgumentException.class, + () -> mIPackageManager.isPackageSignedByKeySet( + CROSS_USER_TEST_PACKAGE_NAME, keySet)); + + installPackageForUser(CROSS_USER_TEST_APK_FILE, mOtherUser); + + assertThrows(IllegalArgumentException.class, + () -> mIPackageManager.isPackageSignedByKeySet( + CROSS_USER_TEST_PACKAGE_NAME, keySet)); + } + + @Test + public void testIsPackageSignedByKeySetExactly_cannotDetectCrossUserPkg() throws Exception { + final KeySet keySet = mIPackageManager.getSigningKeySet(mContext.getPackageName()); + assertThrows(IllegalArgumentException.class, + () -> mIPackageManager.isPackageSignedByKeySetExactly( + CROSS_USER_TEST_PACKAGE_NAME, keySet)); + + installPackageForUser(CROSS_USER_TEST_APK_FILE, mOtherUser); + + assertThrows(IllegalArgumentException.class, + () -> mIPackageManager.isPackageSignedByKeySetExactly( + CROSS_USER_TEST_PACKAGE_NAME, keySet)); + } + + @Test + public void testGetSigningKeySet_cannotDetectCrossUserPkg() { + final IllegalArgumentException e1 = assertThrows(IllegalArgumentException.class, + () -> mIPackageManager.getSigningKeySet(CROSS_USER_TEST_PACKAGE_NAME)); + + installPackageForUser(CROSS_USER_TEST_APK_FILE, mOtherUser); + + final IllegalArgumentException e2 = assertThrows(IllegalArgumentException.class, + () -> mIPackageManager.getSigningKeySet(CROSS_USER_TEST_PACKAGE_NAME)); + assertThat(e1.getMessage()).isEqualTo(e2.getMessage()); + } + + @Test + public void testGetKeySetByAlias_cannotDetectCrossUserPkg() { + final String alias = CROSS_USER_TEST_PACKAGE_NAME + ".alias"; + final IllegalArgumentException e1 = assertThrows(IllegalArgumentException.class, + () -> mIPackageManager.getKeySetByAlias(CROSS_USER_TEST_PACKAGE_NAME, alias)); + + installPackageForUser(CROSS_USER_TEST_APK_FILE, mOtherUser); + + final IllegalArgumentException e2 = assertThrows(IllegalArgumentException.class, + () -> mIPackageManager.getKeySetByAlias(CROSS_USER_TEST_PACKAGE_NAME, alias)); + assertThat(e1.getMessage()).isEqualTo(e2.getMessage()); + } + + private static void installPackageForUser(File apk, UserReference user) { + assertThat(apk.exists()).isTrue(); + final StringBuilder cmd = new StringBuilder("pm install --user "); + cmd.append(user.id()).append(" "); + cmd.append(apk.getPath()); + final String result = runShellCommand(cmd.toString()); + assertThat(result.trim()).contains("Success"); + } + + private static void uninstallPackage(String packageName) { + runShellCommand("pm uninstall " + packageName); + } +} diff --git a/services/tests/PackageManagerServiceTests/appenumeration/test-apps/target/Android.bp b/services/tests/PackageManagerServiceTests/appenumeration/test-apps/target/Android.bp index e0f83272f7a8..99211062964e 100644 --- a/services/tests/PackageManagerServiceTests/appenumeration/test-apps/target/Android.bp +++ b/services/tests/PackageManagerServiceTests/appenumeration/test-apps/target/Android.bp @@ -62,3 +62,17 @@ android_test_helper_app { test_suites: ["device-tests"], platform_apis: true, } + +android_test_helper_app { + name: "AppEnumerationCrossUserPackageVisibilityTestApp", + srcs: ["src/**/*.java"], + manifest: "AndroidManifest-crossUserPackageVisibility.xml", + dex_preopt: { + enabled: false, + }, + optimize: { + enabled: false, + }, + test_suites: ["device-tests"], + platform_apis: true, +} diff --git a/core/res/res/xml-watch/default_zen_mode_config.xml b/services/tests/PackageManagerServiceTests/appenumeration/test-apps/target/AndroidManifest-crossUserPackageVisibility.xml index 938cc0c3f7c0..874a1fc5ff3e 100644 --- a/core/res/res/xml-watch/default_zen_mode_config.xml +++ b/services/tests/PackageManagerServiceTests/appenumeration/test-apps/target/AndroidManifest-crossUserPackageVisibility.xml @@ -1,24 +1,22 @@ <?xml version="1.0" encoding="utf-8"?> <!-- - Copyright 2016, The Android Open Source Project + Copyright (C) 2022 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + 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. ---> + --> -<!-- Default configuration for zen mode. See android.service.notification.ZenModeConfig. --> -<zen version="2"> - <!-- Allow starred contacts to go through only. - Repeated calls, calls, messages, reminders, events off. --> - <allow from="2" repeatCallers="false" calls="false" messages="false" reminders="false" - events="false"/> -</zen> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.appenumeration.crossuserpackagevisibility"> + <application> + </application> +</manifest> diff --git a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java index a2e813aed720..82334f29099d 100644 --- a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java @@ -59,6 +59,7 @@ import androidx.test.runner.AndroidJUnit4; import com.android.dx.mockito.inline.extended.StaticMockitoSession; import com.android.server.LocalServices; import com.android.server.pm.parsing.pkg.AndroidPackage; +import com.android.server.pm.pkg.PackageStateInternal; import org.junit.After; import org.junit.Before; @@ -136,14 +137,17 @@ public class AppOpsServiceTest { .spyStatic(Settings.Global.class) .startMocking(); - // Mock LocalServices.getService(PackageManagerInternal.class).getPackage dependency - // needed by AppOpsService + // Mock LocalServices.getService(PackageManagerInternal.class).getPackageStateInternal + // and getPackage dependency needed by AppOpsService PackageManagerInternal mockPackageManagerInternal = mock(PackageManagerInternal.class); + PackageStateInternal mockMyPSInternal = mock(PackageStateInternal.class); AndroidPackage mockMyPkg = mock(AndroidPackage.class); when(mockMyPkg.isPrivileged()).thenReturn(false); when(mockMyPkg.getUid()).thenReturn(mMyUid); when(mockMyPkg.getAttributions()).thenReturn(Collections.emptyList()); + when(mockPackageManagerInternal.getPackageStateInternal(sMyPackageName)) + .thenReturn(mockMyPSInternal); when(mockPackageManagerInternal.getPackage(sMyPackageName)).thenReturn(mockMyPkg); doReturn(mockPackageManagerInternal).when( () -> LocalServices.getService(PackageManagerInternal.class)); diff --git a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java index cc64797578e7..cb21dce045c1 100644 --- a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java @@ -567,6 +567,40 @@ public class LocalDisplayAdapterTest { } @Test + public void testAfterDisplayStateChanges_committedSetAfterState() throws Exception { + FakeDisplay display = new FakeDisplay(PORT_A); + setUpDisplay(display); + updateAvailableDisplays(); + mAdapter.registerLocked(); + waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS); + assertThat(mListener.addedDisplays.size()).isEqualTo(1); + DisplayDevice displayDevice = mListener.addedDisplays.get(0); + + // Turn off. + Runnable changeStateRunnable = displayDevice.requestDisplayStateLocked(Display.STATE_OFF, 0, + 0); + waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS); + assertThat(mListener.changedDisplays.size()).isEqualTo(1); + mListener.changedDisplays.clear(); + assertThat(displayDevice.getDisplayDeviceInfoLocked().state).isEqualTo(Display.STATE_OFF); + assertThat(displayDevice.getDisplayDeviceInfoLocked().committedState).isNotEqualTo( + Display.STATE_OFF); + verify(mSurfaceControlProxy, never()).setDisplayPowerMode(display.token, Display.STATE_OFF); + + // Execute powerstate change. + changeStateRunnable.run(); + waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS); + + + // Verify that committed triggered a new change event and is set correctly. + verify(mSurfaceControlProxy, never()).setDisplayPowerMode(display.token, Display.STATE_OFF); + assertThat(mListener.changedDisplays.size()).isEqualTo(1); + assertThat(displayDevice.getDisplayDeviceInfoLocked().state).isEqualTo(Display.STATE_OFF); + assertThat(displayDevice.getDisplayDeviceInfoLocked().committedState).isEqualTo( + Display.STATE_OFF); + } + + @Test public void testAfterDisplayChange_GameContentTypeSupportIsUpdated() throws Exception { FakeDisplay display = new FakeDisplay(PORT_A); display.dynamicInfo.gameContentTypeSupported = true; diff --git a/services/tests/mockingservicestests/src/com/android/server/display/color/DisplayWhiteBalanceTintControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/display/color/DisplayWhiteBalanceTintControllerTest.java index b9551999cacb..bc9e9bb9bce8 100644 --- a/services/tests/mockingservicestests/src/com/android/server/display/color/DisplayWhiteBalanceTintControllerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/display/color/DisplayWhiteBalanceTintControllerTest.java @@ -38,7 +38,6 @@ import com.android.internal.R; import org.junit.After; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -191,7 +190,6 @@ public class DisplayWhiteBalanceTintControllerTest { * Matrix should match the precalculated one for given cct and display primaries. */ @Test - @Ignore public void displayWhiteBalance_validateTransformMatrix() { DisplayPrimaries displayPrimaries = new DisplayPrimaries(); displayPrimaries.red = new CieXyz(); @@ -226,12 +224,12 @@ public class DisplayWhiteBalanceTintControllerTest { float[] matrixDwb = mDisplayWhiteBalanceTintController.getMatrix(); final float[] expectedMatrixDwb = { - 0.962880f, -0.001780f, -0.000158f, 0.0f, - 0.035765f, 0.929988f, 0.000858f, 0.0f, - 0.001354f, -0.000470f, 0.948327f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f + 0.971848f, -0.001421f, 0.000491f, 0.0f, + 0.028193f, 0.945798f, 0.003207f, 0.0f, + -0.000042f, -0.000989f, 0.988659f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f }; - assertArrayEquals("Unexpected DWB matrix", matrixDwb, expectedMatrixDwb, + assertArrayEquals("Unexpected DWB matrix", expectedMatrixDwb, matrixDwb, 1e-6f /* tolerance */); } diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/DistractingPackageHelperTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/DistractingPackageHelperTest.kt index cf6c82f23730..0d2e666e431e 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/DistractingPackageHelperTest.kt +++ b/services/tests/mockingservicestests/src/com/android/server/pm/DistractingPackageHelperTest.kt @@ -29,6 +29,7 @@ import org.junit.runners.JUnit4 import org.mockito.ArgumentMatchers.anyInt import org.mockito.Mockito.clearInvocations import org.mockito.Mockito.never +import org.mockito.Mockito.times import org.mockito.Mockito.verify @RunWith(JUnit4::class) @@ -192,4 +193,70 @@ class DistractingPackageHelperTest : PackageHelperTestBase() { Intent.ACTION_DISTRACTING_PACKAGES_CHANGED), nullable(), nullable(), anyInt(), nullable(), nullable(), any(), nullable(), nullable(), nullable()) } + + @Test + fun sendDistractingPackagesChanged_withSameVisibilityAllowList() { + mockAllowList(packageSetting1, allowList(10001, 10002, 10003)) + mockAllowList(packageSetting2, allowList(10001, 10002, 10003)) + + distractingPackageHelper.sendDistractingPackagesChanged(pms.snapshotComputer(), + packagesToChange, uidsToChange, TEST_USER_ID, + PackageManager.RESTRICTION_HIDE_NOTIFICATIONS) + testHandler.flush() + verify(broadcastHelper).sendPackageBroadcast(eq(Intent.ACTION_DISTRACTING_PACKAGES_CHANGED), + nullable(), bundleCaptor.capture(), anyInt(), nullable(), nullable(), any(), + nullable(), nullable(), nullable()) + + var changedPackages = bundleCaptor.value.getStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST) + var changedUids = bundleCaptor.value.getIntArray(Intent.EXTRA_CHANGED_UID_LIST) + assertThat(changedPackages).asList().containsExactly(TEST_PACKAGE_1, TEST_PACKAGE_2) + assertThat(changedUids).asList().containsExactly( + packageSetting1.appId, packageSetting2.appId) + } + + @Test + fun sendDistractingPackagesChanged_withDifferentVisibilityAllowList() { + mockAllowList(packageSetting1, allowList(10001, 10002, 10003)) + mockAllowList(packageSetting2, allowList(10001, 10002, 10004)) + + distractingPackageHelper.sendDistractingPackagesChanged(pms.snapshotComputer(), + packagesToChange, uidsToChange, TEST_USER_ID, + PackageManager.RESTRICTION_HIDE_NOTIFICATIONS) + testHandler.flush() + verify(broadcastHelper, times(2)).sendPackageBroadcast( + eq(Intent.ACTION_DISTRACTING_PACKAGES_CHANGED), nullable(), bundleCaptor.capture(), + anyInt(), nullable(), nullable(), any(), nullable(), nullable(), nullable()) + + bundleCaptor.allValues.forEach { + var changedPackages = it.getStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST) + var changedUids = it.getIntArray(Intent.EXTRA_CHANGED_UID_LIST) + assertThat(changedPackages?.size).isEqualTo(1) + assertThat(changedUids?.size).isEqualTo(1) + assertThat(changedPackages?.get(0)).isAnyOf(TEST_PACKAGE_1, TEST_PACKAGE_2) + assertThat(changedUids?.get(0)).isAnyOf(packageSetting1.appId, packageSetting2.appId) + } + } + + @Test + fun sendDistractingPackagesChanged_withNullVisibilityAllowList() { + mockAllowList(packageSetting1, allowList(10001, 10002, 10003)) + mockAllowList(packageSetting2, null /* list */) + + distractingPackageHelper.sendDistractingPackagesChanged(pms.snapshotComputer(), + packagesToChange, uidsToChange, TEST_USER_ID, + PackageManager.RESTRICTION_HIDE_NOTIFICATIONS) + testHandler.flush() + verify(broadcastHelper, times(2)).sendPackageBroadcast( + eq(Intent.ACTION_DISTRACTING_PACKAGES_CHANGED), nullable(), bundleCaptor.capture(), + anyInt(), nullable(), nullable(), any(), nullable(), nullable(), nullable()) + + bundleCaptor.allValues.forEach { + var changedPackages = it.getStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST) + var changedUids = it.getIntArray(Intent.EXTRA_CHANGED_UID_LIST) + assertThat(changedPackages?.size).isEqualTo(1) + assertThat(changedUids?.size).isEqualTo(1) + assertThat(changedPackages?.get(0)).isAnyOf(TEST_PACKAGE_1, TEST_PACKAGE_2) + assertThat(changedUids?.get(0)).isAnyOf(packageSetting1.appId, packageSetting2.appId) + } + } }
\ No newline at end of file diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageHelperTestBase.kt b/services/tests/mockingservicestests/src/com/android/server/pm/PackageHelperTestBase.kt index bd012fc7837e..f48d16f91af1 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/PackageHelperTestBase.kt +++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageHelperTestBase.kt @@ -20,6 +20,8 @@ import android.os.Build import android.os.Bundle import android.os.UserHandle import android.os.UserManager +import android.util.ArrayMap +import android.util.SparseArray import com.android.server.pm.pkg.PackageStateInternal import com.android.server.testutils.TestHandler import com.android.server.testutils.any @@ -31,6 +33,7 @@ import org.mockito.ArgumentCaptor import org.mockito.Captor import org.mockito.Mock import org.mockito.Mockito +import org.mockito.Mockito.argThat import org.mockito.Mockito.spy import org.mockito.MockitoAnnotations @@ -138,4 +141,15 @@ open class PackageHelperTestBase { rule.system().validateFinalState() return pms } + + protected fun allowList(vararg uids: Int) = SparseArray<IntArray>().apply { + this.put(TEST_USER_ID, uids) + } + + protected fun mockAllowList(pkgSetting: PackageStateInternal, list: SparseArray<IntArray>?) { + whenever(rule.mocks().appsFilter.getVisibilityAllowList( + argThat { it?.packageName == pkgSetting.packageName }, any(IntArray::class.java), + any() as ArrayMap<String, out PackageStateInternal> + )).thenReturn(list) + } }
\ No newline at end of file diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt index 3ba9ca591fb3..121cbe3c7a45 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt +++ b/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt @@ -20,19 +20,14 @@ import android.content.Intent import android.content.pm.SuspendDialogInfo import android.os.Binder import android.os.PersistableBundle -import android.util.ArrayMap -import android.util.SparseArray -import com.android.server.pm.pkg.PackageStateInternal import com.android.server.testutils.any import com.android.server.testutils.eq import com.android.server.testutils.nullable -import com.android.server.testutils.whenever import com.google.common.truth.Truth.assertThat import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 import org.mockito.ArgumentMatchers.anyInt -import org.mockito.Mockito.argThat import org.mockito.Mockito.times import org.mockito.Mockito.verify @@ -382,16 +377,4 @@ class SuspendPackageHelperTest : PackageHelperTestBase() { assertThat(modifiedUids).asList().containsExactly( packageSetting1.appId, packageSetting2.appId) } - - private fun allowList(vararg uids: Int) = SparseArray<IntArray>().apply { - this.put(TEST_USER_ID, uids) - } - - private fun mockAllowList(pkgSetting: PackageStateInternal, list: SparseArray<IntArray>?) { - whenever(rule.mocks().appsFilter.getVisibilityAllowList( - argThat { it?.packageName == pkgSetting.packageName }, any(IntArray::class.java), - any() as ArrayMap<String, out PackageStateInternal> - )) - .thenReturn(list) - } } diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java index d5c5745d6680..f28ad79c8488 100644 --- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java @@ -37,8 +37,8 @@ import android.accounts.AccountManagerInternal; import android.accounts.CantAddAccountActivity; import android.accounts.IAccountManagerResponse; import android.app.AppOpsManager; -import android.app.PropertyInvalidatedCache; import android.app.INotificationManager; +import android.app.PropertyInvalidatedCache; import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManagerInternal; import android.content.BroadcastReceiver; @@ -253,6 +253,26 @@ public class AccountManagerServiceTest extends AndroidTestCase { } @SmallTest + public void testCheckAddAccountLongName() throws Exception { + unlockSystemUser(); + String longString = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaa"; + Account a11 = new Account(longString, AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1); + + mAms.addAccountExplicitly( + a11, /* password= */ "p11", /* extras= */ null, /* callerPackage= */ null); + + String[] list = new String[]{AccountManagerServiceTestFixtures.CALLER_PACKAGE}; + when(mMockPackageManager.getPackagesForUid(anyInt())).thenReturn(list); + Account[] accounts = mAms.getAccountsAsUser(null, + UserHandle.getCallingUserId(), mContext.getOpPackageName()); + assertEquals(0, accounts.length); + } + + + @SmallTest public void testPasswords() throws Exception { unlockSystemUser(); Account a11 = new Account("account1", AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1); diff --git a/services/tests/servicestests/src/com/android/server/backup/restore/FullRestoreEngineTest.java b/services/tests/servicestests/src/com/android/server/backup/restore/FullRestoreEngineTest.java new file mode 100644 index 000000000000..049c745fc128 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/backup/restore/FullRestoreEngineTest.java @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.backup.restore; + +import static com.google.common.truth.Truth.assertWithMessage; + +import android.app.backup.BackupAgent; +import android.platform.test.annotations.Presubmit; +import android.system.OsConstants; + +import androidx.test.runner.AndroidJUnit4; + +import com.android.server.backup.FileMetadata; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +@Presubmit +@RunWith(AndroidJUnit4.class) +public class FullRestoreEngineTest { + private static final String DEFAULT_PACKAGE_NAME = "package"; + private static final String DEFAULT_DOMAIN_NAME = "domain"; + private static final String NEW_PACKAGE_NAME = "new_package"; + private static final String NEW_DOMAIN_NAME = "new_domain"; + + private FullRestoreEngine mRestoreEngine; + + @Before + public void setUp() { + mRestoreEngine = new FullRestoreEngine(); + } + + @Test + public void shouldSkipReadOnlyDir_skipsAllReadonlyDirsAndTheirChildren() { + // Create the file tree. + TestFile[] testFiles = new TestFile[] { + TestFile.dir("root"), + TestFile.file("root/auth_token"), + TestFile.dir("root/media"), + TestFile.file("root/media/picture1.png"), + TestFile.file("root/push_token.txt"), + TestFile.dir("root/read-only-dir-1").markReadOnly().expectSkipped(), + TestFile.dir("root/read-only-dir-1/writable-subdir").expectSkipped(), + TestFile.file("root/read-only-dir-1/writable-subdir/writable-file").expectSkipped(), + TestFile.dir("root/read-only-dir-1/writable-subdir/read-only-subdir-2") + .markReadOnly().expectSkipped(), + TestFile.file("root/read-only-dir-1/writable-file").expectSkipped(), + TestFile.file("root/random-stuff.txt"), + TestFile.dir("root/database"), + TestFile.file("root/database/users.db"), + TestFile.dir("root/read-only-dir-2").markReadOnly().expectSkipped(), + TestFile.file("root/read-only-dir-2/writable-file-1").expectSkipped(), + TestFile.file("root/read-only-dir-2/writable-file-2").expectSkipped(), + }; + + assertCorrectItemsAreSkipped(testFiles); + } + + @Test + public void shouldSkipReadOnlyDir_onlySkipsChildrenUnderTheSamePackage() { + TestFile[] testFiles = new TestFile[]{ + TestFile.dir("read-only-dir").markReadOnly().expectSkipped(), + TestFile.file("read-only-dir/file").expectSkipped(), + TestFile.file("read-only-dir/file-from-different-package") + .setPackage(NEW_PACKAGE_NAME), + }; + + assertCorrectItemsAreSkipped(testFiles); + } + + @Test + public void shouldSkipReadOnlyDir_onlySkipsChildrenUnderTheSameDomain() { + TestFile[] testFiles = new TestFile[]{ + TestFile.dir("read-only-dir").markReadOnly().expectSkipped(), + TestFile.file("read-only-dir/file").expectSkipped(), + TestFile.file("read-only-dir/file-from-different-domain") + .setDomain(NEW_DOMAIN_NAME), + }; + + assertCorrectItemsAreSkipped(testFiles); + } + + private void assertCorrectItemsAreSkipped(TestFile[] testFiles) { + // Verify all directories marked with .expectSkipped are skipped. + for (TestFile testFile : testFiles) { + boolean actualExcluded = mRestoreEngine.shouldSkipReadOnlyDir(testFile.mMetadata); + boolean expectedExcluded = testFile.mShouldSkip; + assertWithMessage(testFile.mMetadata.path).that(actualExcluded).isEqualTo( + expectedExcluded); + } + } + + private static class TestFile { + private final FileMetadata mMetadata; + private boolean mShouldSkip; + + static TestFile dir(String path) { + return new TestFile(path, BackupAgent.TYPE_DIRECTORY); + } + + static TestFile file(String path) { + return new TestFile(path, BackupAgent.TYPE_FILE); + } + + TestFile markReadOnly() { + mMetadata.mode = 0; + return this; + } + + TestFile expectSkipped() { + mShouldSkip = true; + return this; + } + + TestFile setPackage(String packageName) { + mMetadata.packageName = packageName; + return this; + } + + TestFile setDomain(String domain) { + mMetadata.domain = domain; + return this; + } + + private TestFile(String path, int type) { + FileMetadata metadata = new FileMetadata(); + metadata.path = path; + metadata.type = type; + metadata.packageName = DEFAULT_PACKAGE_NAME; + metadata.domain = DEFAULT_DOMAIN_NAME; + metadata.mode = OsConstants.S_IWUSR; // Mark as writable. + mMetadata = metadata; + } + } +} diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java index aba93b058669..f08d0ef67df3 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java @@ -18,6 +18,7 @@ package com.android.server.biometrics.sensors.face.aidl; 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.eq; import static org.mockito.Mockito.inOrder; @@ -26,8 +27,13 @@ import static org.mockito.Mockito.same; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.app.ActivityManager; +import android.app.ActivityTaskManager; +import android.content.ComponentName; +import android.hardware.biometrics.common.ICancellationSignal; import android.hardware.biometrics.common.OperationContext; import android.hardware.biometrics.face.ISession; +import android.hardware.face.Face; import android.os.IBinder; import android.os.RemoteException; import android.platform.test.annotations.Presubmit; @@ -53,6 +59,9 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; +import java.util.ArrayList; +import java.util.List; + @Presubmit @SmallTest public class FaceAuthenticationClientTest { @@ -82,6 +91,10 @@ public class FaceAuthenticationClientTest { private ClientMonitorCallback mCallback; @Mock private Sensor.HalSessionCallback mHalSessionCallback; + @Mock + private ActivityTaskManager mActivityTaskManager; + @Mock + private ICancellationSignal mCancellationSignal; @Captor private ArgumentCaptor<OperationContext> mOperationContextCaptor; @@ -116,6 +129,25 @@ public class FaceAuthenticationClientTest { verify(mHal, never()).authenticate(anyLong()); } + @Test + public void cancelsAuthWhenNotInForeground() throws Exception { + final ActivityManager.RunningTaskInfo topTask = new ActivityManager.RunningTaskInfo(); + topTask.topActivity = new ComponentName("other", "thing"); + when(mActivityTaskManager.getTasks(anyInt())).thenReturn(List.of(topTask)); + when(mHal.authenticateWithContext(anyLong(), any())).thenReturn(mCancellationSignal); + + final FaceAuthenticationClient client = createClient(); + client.start(mCallback); + client.onAuthenticated(new Face("friendly", 1 /* faceId */, 2 /* deviceId */), + true /* authenticated */, new ArrayList<>()); + + verify(mCancellationSignal).cancel(); + } + + private FaceAuthenticationClient createClient() throws RemoteException { + return createClient(2 /* version */); + } + private FaceAuthenticationClient createClient(int version) throws RemoteException { when(mHal.getInterfaceVersion()).thenReturn(version); @@ -126,6 +158,11 @@ public class FaceAuthenticationClientTest { false /* requireConfirmation */, 9 /* sensorId */, mBiometricLogger, mBiometricContext, true /* isStrongBiometric */, mUsageStats, mLockoutCache, false /* allowBackgroundAuthentication */, - false /* isKeyguardBypassEnabled */, null /* sensorPrivacyManager */); + false /* isKeyguardBypassEnabled */, null /* sensorPrivacyManager */) { + @Override + protected ActivityTaskManager getActivityTaskManager() { + return mActivityTaskManager; + } + }; } } diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java index 746302224d21..1a49f8aa2e6a 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java @@ -31,7 +31,11 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.app.ActivityManager; +import android.app.ActivityTaskManager; +import android.content.ComponentName; import android.hardware.biometrics.BiometricManager; +import android.hardware.biometrics.common.ICancellationSignal; import android.hardware.biometrics.common.OperationContext; import android.hardware.biometrics.fingerprint.ISession; import android.hardware.biometrics.fingerprint.PointerContext; @@ -66,6 +70,7 @@ import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import java.util.ArrayList; +import java.util.List; import java.util.function.Consumer; @Presubmit @@ -111,6 +116,10 @@ public class FingerprintAuthenticationClientTest { @Mock private Sensor.HalSessionCallback mHalSessionCallback; @Mock + private ActivityTaskManager mActivityTaskManager; + @Mock + private ICancellationSignal mCancellationSignal; + @Mock private Probe mLuxProbe; @Captor private ArgumentCaptor<OperationContext> mOperationContextCaptor; @@ -288,11 +297,36 @@ public class FingerprintAuthenticationClientTest { verify(mSideFpsController).hide(anyInt()); } + @Test + public void cancelsAuthWhenNotInForeground() throws Exception { + final ActivityManager.RunningTaskInfo topTask = new ActivityManager.RunningTaskInfo(); + topTask.topActivity = new ComponentName("other", "thing"); + when(mActivityTaskManager.getTasks(anyInt())).thenReturn(List.of(topTask)); + when(mHal.authenticateWithContext(anyLong(), any())).thenReturn(mCancellationSignal); + + final FingerprintAuthenticationClient client = createClientWithoutBackgroundAuth(); + client.start(mCallback); + client.onAuthenticated(new Fingerprint("friendly", 1 /* fingerId */, 2 /* deviceId */), + true /* authenticated */, new ArrayList<>()); + + verify(mCancellationSignal).cancel(); + } + private FingerprintAuthenticationClient createClient() throws RemoteException { - return createClient(100); + return createClient(100 /* version */, true /* allowBackgroundAuthentication */); + } + + private FingerprintAuthenticationClient createClientWithoutBackgroundAuth() + throws RemoteException { + return createClient(100 /* version */, false /* allowBackgroundAuthentication */); } private FingerprintAuthenticationClient createClient(int version) throws RemoteException { + return createClient(version, true /* allowBackgroundAuthentication */); + } + + private FingerprintAuthenticationClient createClient(int version, + boolean allowBackgroundAuthentication) throws RemoteException { when(mHal.getInterfaceVersion()).thenReturn(version); final AidlSession aidl = new AidlSession(version, mHal, USER_ID, mHalSessionCallback); @@ -302,7 +336,11 @@ public class FingerprintAuthenticationClientTest { 9 /* sensorId */, mBiometricLogger, mBiometricContext, true /* isStrongBiometric */, null /* taskStackListener */, mLockoutCache, - mUdfpsOverlayController, mSideFpsController, - true /* allowBackgroundAuthentication */, mSensorProps); + mUdfpsOverlayController, mSideFpsController, allowBackgroundAuthentication, mSensorProps) { + @Override + protected ActivityTaskManager getActivityTaskManager() { + return mActivityTaskManager; + } + }; } } 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 new file mode 100644 index 000000000000..282c782e752a --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClientTest.java @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.biometrics.sensors.fingerprint.aidl; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.hardware.biometrics.BiometricAuthenticator; +import android.hardware.biometrics.fingerprint.ISession; +import android.hardware.fingerprint.Fingerprint; +import android.platform.test.annotations.Presubmit; +import android.testing.TestableContext; + +import androidx.annotation.NonNull; +import androidx.test.filters.SmallTest; +import androidx.test.platform.app.InstrumentationRegistry; + +import com.android.server.biometrics.log.BiometricContext; +import com.android.server.biometrics.log.BiometricLogger; +import com.android.server.biometrics.sensors.ClientMonitorCallback; +import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils; + +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Presubmit +@SmallTest +public class FingerprintInternalCleanupClientTest { + + private static final int SENSOR_ID = 22; + + @Rule + public final MockitoRule mockito = MockitoJUnit.rule(); + + @Rule + public final TestableContext mContext = new TestableContext( + InstrumentationRegistry.getInstrumentation().getTargetContext(), null); + + @Mock + private AidlSession mAidlSession; + @Mock + private ISession mSession; + @Mock + private BiometricLogger mLogger; + @Mock + private BiometricContext mBiometricContext; + @Mock + private FingerprintUtils mFingerprintUtils; + @Mock + private ClientMonitorCallback mCallback; + + private FingerprintInternalCleanupClient mClient; + private List<Integer> mAddedIds; + + @Before + public void setup() { + when(mAidlSession.getSession()).thenReturn(mSession); + mAddedIds = new ArrayList<>(); + } + + @Ignore("TODO(b/229015801): verify cleanup behavior") + @Test + public void removesUnknownTemplate() throws Exception { + mClient = createClient(); + + final List<Fingerprint> templates = List.of( + new Fingerprint("one", 1, 1), + new Fingerprint("two", 2, 1) + ); + mClient.start(mCallback); + for (int i = templates.size() - 1; i >= 0; i--) { + mClient.getCurrentEnumerateClient().onEnumerationResult(templates.get(i), i); + } + for (int i = templates.size() - 1; i >= 0; i--) { + mClient.getCurrentRemoveClient().onRemoved(templates.get(i), 0); + } + + assertThat(mAddedIds).isEmpty(); + final ArgumentCaptor<int[]> captor = ArgumentCaptor.forClass(int[].class); + verify(mSession, times(2)).removeEnrollments(captor.capture()); + assertThat(captor.getAllValues().stream() + .flatMap(x -> Arrays.stream(x).boxed()) + .collect(Collectors.toList())) + .containsExactly(1, 2); + verify(mCallback).onClientFinished(eq(mClient), eq(true)); + } + + @Test + public void addsUnknownTemplateWhenVirtualIsEnabled() throws Exception { + mClient = createClient(); + mClient.setFavorHalEnrollments(); + + final List<Fingerprint> templates = List.of( + new Fingerprint("one", 1, 1), + new Fingerprint("two", 2, 1) + ); + mClient.start(mCallback); + for (int i = templates.size() - 1; i >= 0; i--) { + mClient.getCurrentEnumerateClient().onEnumerationResult(templates.get(i), i); + } + + assertThat(mAddedIds).containsExactly(1, 2); + verify(mSession, never()).removeEnrollments(any()); + verify(mCallback).onClientFinished(eq(mClient), eq(true)); + } + + protected FingerprintInternalCleanupClient createClient() { + final List<Fingerprint> enrollments = new ArrayList<>(); + final Map<Integer, Long> authenticatorIds = new HashMap<>(); + return new FingerprintInternalCleanupClient(mContext, () -> mAidlSession, 2 /* userId */, + "the.test.owner", SENSOR_ID, mLogger, mBiometricContext, enrollments, + mFingerprintUtils, authenticatorIds) { + @Override + protected void onAddUnknownTemplate(int userId, + @NonNull BiometricAuthenticator.Identifier identifier) { + mAddedIds.add(identifier.getBiometricId()); + } + }; + } +} diff --git a/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java index fe3034dc569d..ce7b367ec7ec 100644 --- a/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java @@ -243,6 +243,7 @@ public final class DeviceStateManagerServiceTest { assertEquals(info.currentState, DEFAULT_DEVICE_STATE.getIdentifier()); } + @FlakyTest(bugId = 223153452) @Test public void registerCallback() throws RemoteException { TestDeviceStateManagerCallback callback = new TestDeviceStateManagerCallback(); diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java index bf3c7c3e05fb..64c71279520b 100644 --- a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java @@ -206,7 +206,7 @@ public class DisplayManagerServiceTest { DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector); registerDefaultDisplays(displayManager); - displayManager.systemReady(false /* safeMode */, true /* onlyCore */); + displayManager.systemReady(false /* safeMode */); displayManager.windowManagerAndInputReady(); // This is effectively the DisplayManager service published to ServiceManager. @@ -278,7 +278,7 @@ public class DisplayManagerServiceTest { DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector); registerDefaultDisplays(displayManager); - displayManager.systemReady(false /* safeMode */, true /* onlyCore */); + displayManager.systemReady(false /* safeMode */); displayManager.windowManagerAndInputReady(); // This is effectively the DisplayManager service published to ServiceManager. diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java index 484b5a8dae1a..0f6addb452a1 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java @@ -982,7 +982,11 @@ public class HdmiCecLocalDevicePlaybackTest { } @Test - public void handleOnInitializeCecComplete_ByScreenOn() { + public void handleOnInitializeCecComplete_ByScreenOn_PowerControlModeTv() { + mHdmiCecLocalDevicePlayback.mService.getHdmiCecConfig().setStringValue( + HdmiControlManager.CEC_SETTING_NAME_POWER_CONTROL_MODE, + HdmiControlManager.POWER_CONTROL_MODE_TV); + mHdmiCecLocalDevicePlayback.onInitializeCecComplete( mHdmiControlService.INITIATED_BY_SCREEN_ON); mTestLooper.dispatchAll(); @@ -999,6 +1003,27 @@ public class HdmiCecLocalDevicePlaybackTest { } @Test + public void handleOnInitializeCecComplete_ByScreenOn_PowerControlModeNone() { + mHdmiCecLocalDevicePlayback.mService.getHdmiCecConfig().setStringValue( + HdmiControlManager.CEC_SETTING_NAME_POWER_CONTROL_MODE, + HdmiControlManager.POWER_CONTROL_MODE_NONE); + + mHdmiCecLocalDevicePlayback.onInitializeCecComplete( + mHdmiControlService.INITIATED_BY_SCREEN_ON); + mTestLooper.dispatchAll(); + + HdmiCecMessage activeSource = + HdmiCecMessageBuilder.buildActiveSource(mPlaybackLogicalAddress, + mPlaybackPhysicalAddress); + HdmiCecMessage textViewOn = + HdmiCecMessageBuilder.buildTextViewOn(mPlaybackLogicalAddress, + ADDR_TV); + + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(activeSource); + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(textViewOn); + } + + @Test public void handleOnInitializeCecComplete_ByWakeUpMessage() { mHdmiCecLocalDevicePlayback.onInitializeCecComplete( mHdmiControlService.INITIATED_BY_WAKE_UP_MESSAGE); diff --git a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java index c7a903be3bd2..1538f0619e1e 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java @@ -89,16 +89,17 @@ public class ApexManagerTest { @Test public void testGetPackageInfo_setFlagsMatchActivePackage() throws RemoteException { - when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(true, false)); - mApexManager.scanApexPackagesTraced(mPackageParser2, - ParallelPackageParser.makeExecutorService()); - final PackageInfo activePkgPi = mApexManager.getPackageInfo(TEST_APEX_PKG, + ApexInfo[] apexInfo = createApexInfoForTestPkg(true, false); + ApexPackageInfo apexPackageInfo = new ApexPackageInfo(); + apexPackageInfo.scanApexPackages( + apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService()); + final PackageInfo activePkgPi = apexPackageInfo.getPackageInfo(TEST_APEX_PKG, ApexManager.MATCH_ACTIVE_PACKAGE); assertThat(activePkgPi).isNotNull(); assertThat(activePkgPi.packageName).contains(TEST_APEX_PKG); - final PackageInfo factoryPkgPi = mApexManager.getPackageInfo(TEST_APEX_PKG, + final PackageInfo factoryPkgPi = apexPackageInfo.getPackageInfo(TEST_APEX_PKG, ApexManager.MATCH_FACTORY_PACKAGE); assertThat(factoryPkgPi).isNull(); @@ -106,16 +107,17 @@ public class ApexManagerTest { @Test public void testGetPackageInfo_setFlagsMatchFactoryPackage() throws RemoteException { - when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(false, true)); - mApexManager.scanApexPackagesTraced(mPackageParser2, - ParallelPackageParser.makeExecutorService()); - PackageInfo factoryPkgPi = mApexManager.getPackageInfo(TEST_APEX_PKG, + ApexInfo[] apexInfo = createApexInfoForTestPkg(false, true); + ApexPackageInfo apexPackageInfo = new ApexPackageInfo(); + apexPackageInfo.scanApexPackages( + apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService()); + PackageInfo factoryPkgPi = apexPackageInfo.getPackageInfo(TEST_APEX_PKG, ApexManager.MATCH_FACTORY_PACKAGE); assertThat(factoryPkgPi).isNotNull(); assertThat(factoryPkgPi.packageName).contains(TEST_APEX_PKG); - final PackageInfo activePkgPi = mApexManager.getPackageInfo(TEST_APEX_PKG, + final PackageInfo activePkgPi = apexPackageInfo.getPackageInfo(TEST_APEX_PKG, ApexManager.MATCH_ACTIVE_PACKAGE); assertThat(activePkgPi).isNull(); @@ -123,23 +125,26 @@ public class ApexManagerTest { @Test public void testGetPackageInfo_setFlagsNone() throws RemoteException { - when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(false, true)); - mApexManager.scanApexPackagesTraced(mPackageParser2, - ParallelPackageParser.makeExecutorService()); + ApexInfo[] apexInfo = createApexInfoForTestPkg(false, true); + ApexPackageInfo apexPackageInfo = new ApexPackageInfo(); + apexPackageInfo.scanApexPackages( + apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService()); - assertThat(mApexManager.getPackageInfo(TEST_APEX_PKG, 0)).isNull(); + assertThat(apexPackageInfo.getPackageInfo(TEST_APEX_PKG, 0)).isNull(); } @Test public void testGetApexSystemServices() throws RemoteException { - when(mApexService.getAllPackages()).thenReturn(new ApexInfo[] { + ApexInfo[] apexInfo = new ApexInfo[] { createApexInfoForTestPkg(false, true, 1), // only active apex reports apex-system-service createApexInfoForTestPkg(true, false, 2), - }); + }; - mApexManager.scanApexPackagesTraced(mPackageParser2, - ParallelPackageParser.makeExecutorService()); + ApexPackageInfo apexPackageInfo = new ApexPackageInfo(); + List<ApexManager.ScanResult> scanResults = apexPackageInfo.scanApexPackages( + apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService()); + mApexManager.notifyScanResult(scanResults); List<ApexSystemServiceInfo> services = mApexManager.getApexSystemServices(); assertThat(services).hasSize(1); @@ -149,65 +154,72 @@ public class ApexManagerTest { @Test public void testGetActivePackages() throws RemoteException { - when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(true, true)); - mApexManager.scanApexPackagesTraced(mPackageParser2, - ParallelPackageParser.makeExecutorService()); + ApexInfo[] apexInfo = createApexInfoForTestPkg(true, true); + ApexPackageInfo apexPackageInfo = new ApexPackageInfo(); + apexPackageInfo.scanApexPackages( + apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService()); - assertThat(mApexManager.getActivePackages()).isNotEmpty(); + assertThat(apexPackageInfo.getActivePackages()).isNotEmpty(); } @Test public void testGetActivePackages_noneActivePackages() throws RemoteException { - when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(false, true)); - mApexManager.scanApexPackagesTraced(mPackageParser2, - ParallelPackageParser.makeExecutorService()); + ApexInfo[] apexInfo = createApexInfoForTestPkg(false, true); + ApexPackageInfo apexPackageInfo = new ApexPackageInfo(); + apexPackageInfo.scanApexPackages( + apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService()); - assertThat(mApexManager.getActivePackages()).isEmpty(); + assertThat(apexPackageInfo.getActivePackages()).isEmpty(); } @Test public void testGetFactoryPackages() throws RemoteException { - when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(false, true)); - mApexManager.scanApexPackagesTraced(mPackageParser2, - ParallelPackageParser.makeExecutorService()); + ApexInfo [] apexInfo = createApexInfoForTestPkg(false, true); + ApexPackageInfo apexPackageInfo = new ApexPackageInfo(); + apexPackageInfo.scanApexPackages( + apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService()); - assertThat(mApexManager.getFactoryPackages()).isNotEmpty(); + assertThat(apexPackageInfo.getFactoryPackages()).isNotEmpty(); } @Test public void testGetFactoryPackages_noneFactoryPackages() throws RemoteException { - when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(true, false)); - mApexManager.scanApexPackagesTraced(mPackageParser2, - ParallelPackageParser.makeExecutorService()); + ApexInfo[] apexInfo = createApexInfoForTestPkg(true, false); + ApexPackageInfo apexPackageInfo = new ApexPackageInfo(); + apexPackageInfo.scanApexPackages( + apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService()); - assertThat(mApexManager.getFactoryPackages()).isEmpty(); + assertThat(apexPackageInfo.getFactoryPackages()).isEmpty(); } @Test public void testGetInactivePackages() throws RemoteException { - when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(false, true)); - mApexManager.scanApexPackagesTraced(mPackageParser2, - ParallelPackageParser.makeExecutorService()); + ApexInfo[] apexInfo = createApexInfoForTestPkg(false, true); + ApexPackageInfo apexPackageInfo = new ApexPackageInfo(); + apexPackageInfo.scanApexPackages( + apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService()); - assertThat(mApexManager.getInactivePackages()).isNotEmpty(); + assertThat(apexPackageInfo.getInactivePackages()).isNotEmpty(); } @Test public void testGetInactivePackages_noneInactivePackages() throws RemoteException { - when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(true, false)); - mApexManager.scanApexPackagesTraced(mPackageParser2, - ParallelPackageParser.makeExecutorService()); + ApexInfo[] apexInfo = createApexInfoForTestPkg(true, false); + ApexPackageInfo apexPackageInfo = new ApexPackageInfo(); + apexPackageInfo.scanApexPackages( + apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService()); - assertThat(mApexManager.getInactivePackages()).isEmpty(); + assertThat(apexPackageInfo.getInactivePackages()).isEmpty(); } @Test public void testIsApexPackage() throws RemoteException { - when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(false, true)); - mApexManager.scanApexPackagesTraced(mPackageParser2, - ParallelPackageParser.makeExecutorService()); + ApexInfo[] apexInfo = createApexInfoForTestPkg(false, true); + ApexPackageInfo apexPackageInfo = new ApexPackageInfo(); + apexPackageInfo.scanApexPackages( + apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService()); - assertThat(mApexManager.isApexPackage(TEST_APEX_PKG)).isTrue(); + assertThat(apexPackageInfo.isApexPackage(TEST_APEX_PKG)).isTrue(); } @Test @@ -317,9 +329,11 @@ public class ApexManagerTest { final ApexManager.ActiveApexInfo activeApex = mApexManager.getActiveApexInfos().get(0); assertThat(activeApex.apexModuleName).isEqualTo(TEST_APEX_PKG); - when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(true, true)); - mApexManager.scanApexPackagesTraced(mPackageParser2, - ParallelPackageParser.makeExecutorService()); + ApexInfo[] apexInfo = createApexInfoForTestPkg(true, true); + ApexPackageInfo apexPackageInfo = new ApexPackageInfo(); + List<ApexManager.ScanResult> scanResults = apexPackageInfo.scanApexPackages( + apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService()); + mApexManager.notifyScanResult(scanResults); assertThat(mApexManager.getApkInApexInstallError(activeApex.apexModuleName)).isNull(); mApexManager.reportErrorWithApkInApex(activeApex.apexDirectory.getAbsolutePath(), @@ -344,9 +358,11 @@ public class ApexManagerTest { when(fakeApkInApex.getBaseApkPath()).thenReturn("/apex/" + TEST_APEX_PKG + "randomSuffix"); when(fakeApkInApex.getPackageName()).thenReturn("randomPackageName"); - when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(true, true)); - mApexManager.scanApexPackagesTraced(mPackageParser2, - ParallelPackageParser.makeExecutorService()); + ApexInfo[] apexInfo = createApexInfoForTestPkg(true, true); + ApexPackageInfo apexPackageInfo = new ApexPackageInfo(); + List<ApexManager.ScanResult> scanResults = apexPackageInfo.scanApexPackages( + apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService()); + mApexManager.notifyScanResult(scanResults); assertThat(mApexManager.getApksInApex(activeApex.apexModuleName)).isEmpty(); mApexManager.registerApkInApex(fakeApkInApex); @@ -355,13 +371,14 @@ public class ApexManagerTest { @Test public void testInstallPackageFailsToInstallNewApex() throws Exception { - when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(true, false)); - mApexManager.scanApexPackagesTraced(mPackageParser2, - ParallelPackageParser.makeExecutorService()); + ApexInfo[] apexInfo = createApexInfoForTestPkg(true, false); + ApexPackageInfo apexPackageInfo = new ApexPackageInfo(); + apexPackageInfo.scanApexPackages( + apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService()); File apex = extractResource("test.apex_rebootless_v1", "test.rebootless_apex_v1.apex"); PackageManagerException e = expectThrows(PackageManagerException.class, - () -> mApexManager.installPackage(apex, mPackageParser2)); + () -> mApexManager.installPackage(apex, mPackageParser2, apexPackageInfo)); assertThat(e).hasMessageThat().contains("It is forbidden to install new APEX packages"); } @@ -370,9 +387,10 @@ public class ApexManagerTest { ApexInfo activeApexInfo = createApexInfo("test.apex_rebootless", 1, /* isActive= */ true, /* isFactory= */ true, extractResource("test.apex_rebootless_v1", "test.rebootless_apex_v1.apex")); - when(mApexService.getAllPackages()).thenReturn(new ApexInfo[]{activeApexInfo}); - mApexManager.scanApexPackagesTraced(mPackageParser2, - ParallelPackageParser.makeExecutorService()); + ApexInfo[] apexInfo = new ApexInfo[]{activeApexInfo}; + ApexPackageInfo apexPackageInfo = new ApexPackageInfo(); + apexPackageInfo.scanApexPackages( + apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService()); File finalApex = extractResource("test.rebootles_apex_v2", "test.rebootless_apex_v2.apex"); ApexInfo newApexInfo = createApexInfo("test.apex_rebootless", 2, /* isActive= */ true, @@ -380,23 +398,26 @@ public class ApexManagerTest { when(mApexService.installAndActivatePackage(anyString())).thenReturn(newApexInfo); File installedApex = extractResource("installed", "test.rebootless_apex_v2.apex"); - mApexManager.installPackage(installedApex, mPackageParser2); + newApexInfo = mApexManager.installPackage(installedApex, mPackageParser2, apexPackageInfo); + apexPackageInfo.notifyPackageInstalled(newApexInfo, mPackageParser2); - PackageInfo newInfo = mApexManager.getPackageInfo("test.apex.rebootless", + PackageInfo newInfo = apexPackageInfo.getPackageInfo("test.apex.rebootless", ApexManager.MATCH_ACTIVE_PACKAGE); assertThat(newInfo.applicationInfo.sourceDir).isEqualTo(finalApex.getAbsolutePath()); assertThat(newInfo.applicationInfo.longVersionCode).isEqualTo(2); - assertThat(newInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM).isEqualTo(0); + assertThat(newInfo.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) + .isEqualTo(ApplicationInfo.FLAG_UPDATED_SYSTEM_APP); assertThat(newInfo.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) .isEqualTo(ApplicationInfo.FLAG_INSTALLED); - PackageInfo factoryInfo = mApexManager.getPackageInfo("test.apex.rebootless", + PackageInfo factoryInfo = apexPackageInfo.getPackageInfo("test.apex.rebootless", ApexManager.MATCH_FACTORY_PACKAGE); assertThat(factoryInfo.applicationInfo.sourceDir).isEqualTo(activeApexInfo.modulePath); assertThat(factoryInfo.applicationInfo.longVersionCode).isEqualTo(1); assertThat(factoryInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) .isEqualTo(ApplicationInfo.FLAG_SYSTEM); - assertThat(factoryInfo.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED).isEqualTo(0); + assertThat(factoryInfo.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) + .isEqualTo(ApplicationInfo.FLAG_INSTALLED); } @Test @@ -407,10 +428,10 @@ public class ApexManagerTest { ApexInfo activeApexInfo = createApexInfo("test.apex_rebootless", 1, /* isActive= */ true, /* isFactory= */ false, extractResource("test.apex.rebootless@1", "test.rebootless_apex_v1.apex")); - when(mApexService.getAllPackages()) - .thenReturn(new ApexInfo[]{factoryApexInfo, activeApexInfo}); - mApexManager.scanApexPackagesTraced(mPackageParser2, - ParallelPackageParser.makeExecutorService()); + ApexInfo[] apexInfo = new ApexInfo[]{factoryApexInfo, activeApexInfo}; + ApexPackageInfo apexPackageInfo = new ApexPackageInfo(); + apexPackageInfo.scanApexPackages( + apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService()); File finalApex = extractResource("test.rebootles_apex_v2", "test.rebootless_apex_v2.apex"); ApexInfo newApexInfo = createApexInfo("test.apex_rebootless", 2, /* isActive= */ true, @@ -418,23 +439,26 @@ public class ApexManagerTest { when(mApexService.installAndActivatePackage(anyString())).thenReturn(newApexInfo); File installedApex = extractResource("installed", "test.rebootless_apex_v2.apex"); - mApexManager.installPackage(installedApex, mPackageParser2); + newApexInfo = mApexManager.installPackage(installedApex, mPackageParser2, apexPackageInfo); + apexPackageInfo.notifyPackageInstalled(newApexInfo, mPackageParser2); - PackageInfo newInfo = mApexManager.getPackageInfo("test.apex.rebootless", + PackageInfo newInfo = apexPackageInfo.getPackageInfo("test.apex.rebootless", ApexManager.MATCH_ACTIVE_PACKAGE); assertThat(newInfo.applicationInfo.sourceDir).isEqualTo(finalApex.getAbsolutePath()); assertThat(newInfo.applicationInfo.longVersionCode).isEqualTo(2); - assertThat(newInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM).isEqualTo(0); + assertThat(newInfo.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) + .isEqualTo(ApplicationInfo.FLAG_UPDATED_SYSTEM_APP); assertThat(newInfo.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) .isEqualTo(ApplicationInfo.FLAG_INSTALLED); - PackageInfo factoryInfo = mApexManager.getPackageInfo("test.apex.rebootless", + PackageInfo factoryInfo = apexPackageInfo.getPackageInfo("test.apex.rebootless", ApexManager.MATCH_FACTORY_PACKAGE); assertThat(factoryInfo.applicationInfo.sourceDir).isEqualTo(factoryApexInfo.modulePath); assertThat(factoryInfo.applicationInfo.longVersionCode).isEqualTo(1); assertThat(factoryInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) .isEqualTo(ApplicationInfo.FLAG_SYSTEM); - assertThat(factoryInfo.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED).isEqualTo(0); + assertThat(factoryInfo.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) + .isEqualTo(ApplicationInfo.FLAG_INSTALLED); } @Test @@ -442,9 +466,10 @@ public class ApexManagerTest { ApexInfo activeApexInfo = createApexInfo("test.apex_rebootless", 1, /* isActive= */ true, /* isFactory= */ false, extractResource("test.apex_rebootless_v1", "test.rebootless_apex_v1.apex")); - when(mApexService.getAllPackages()).thenReturn(new ApexInfo[]{activeApexInfo}); - mApexManager.scanApexPackagesTraced(mPackageParser2, - ParallelPackageParser.makeExecutorService()); + ApexInfo[] apexInfo = new ApexInfo[]{activeApexInfo}; + ApexPackageInfo apexPackageInfo = new ApexPackageInfo(); + apexPackageInfo.scanApexPackages( + apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService()); when(mApexService.installAndActivatePackage(anyString())).thenThrow( new RuntimeException("install failed :(")); @@ -452,7 +477,7 @@ public class ApexManagerTest { File installedApex = extractResource("test.apex_rebootless_v1", "test.rebootless_apex_v1.apex"); assertThrows(PackageManagerException.class, - () -> mApexManager.installPackage(installedApex, mPackageParser2)); + () -> mApexManager.installPackage(installedApex, mPackageParser2, apexPackageInfo)); } @Test @@ -460,14 +485,15 @@ public class ApexManagerTest { File activeApex = extractResource("shim_v1", "com.android.apex.cts.shim.apex"); ApexInfo activeApexInfo = createApexInfo("com.android.apex.cts.shim", 1, /* isActive= */ true, /* isFactory= */ false, activeApex); - when(mApexService.getAllPackages()).thenReturn(new ApexInfo[]{activeApexInfo}); - mApexManager.scanApexPackagesTraced(mPackageParser2, - ParallelPackageParser.makeExecutorService()); + ApexInfo[] apexInfo = new ApexInfo[]{activeApexInfo}; + ApexPackageInfo apexPackageInfo = new ApexPackageInfo(); + apexPackageInfo.scanApexPackages( + apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService()); File installedApex = extractResource("shim_different_certificate", "com.android.apex.cts.shim.v2_different_certificate.apex"); PackageManagerException e = expectThrows(PackageManagerException.class, - () -> mApexManager.installPackage(installedApex, mPackageParser2)); + () -> mApexManager.installPackage(installedApex, mPackageParser2, apexPackageInfo)); assertThat(e).hasMessageThat().contains("APK container signature of "); assertThat(e).hasMessageThat().contains( "is not compatible with currently installed on device"); @@ -478,14 +504,15 @@ public class ApexManagerTest { File activeApex = extractResource("shim_v1", "com.android.apex.cts.shim.apex"); ApexInfo activeApexInfo = createApexInfo("com.android.apex.cts.shim", 1, /* isActive= */ true, /* isFactory= */ false, activeApex); - when(mApexService.getAllPackages()).thenReturn(new ApexInfo[]{activeApexInfo}); - mApexManager.scanApexPackagesTraced(mPackageParser2, - ParallelPackageParser.makeExecutorService()); + ApexInfo[] apexInfo = new ApexInfo[]{activeApexInfo}; + ApexPackageInfo apexPackageInfo = new ApexPackageInfo(); + apexPackageInfo.scanApexPackages( + apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService()); File installedApex = extractResource("shim_unsigned_apk_container", "com.android.apex.cts.shim.v2_unsigned_apk_container.apex"); PackageManagerException e = expectThrows(PackageManagerException.class, - () -> mApexManager.installPackage(installedApex, mPackageParser2)); + () -> mApexManager.installPackage(installedApex, mPackageParser2, apexPackageInfo)); assertThat(e).hasMessageThat().contains("Failed to collect certificates from "); } @@ -495,9 +522,10 @@ public class ApexManagerTest { ApexInfo[] apexInfo = createApexInfoForTestPkg(true, false); apexInfo[0].moduleName = moduleName; - when(mApexService.getAllPackages()).thenReturn(apexInfo); - mApexManager.scanApexPackagesTraced(mPackageParser2, - ParallelPackageParser.makeExecutorService()); + ApexPackageInfo apexPackageInfo = new ApexPackageInfo(); + List<ApexManager.ScanResult> scanResults = apexPackageInfo.scanApexPackages( + apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService()); + mApexManager.notifyScanResult(scanResults); assertThat(mApexManager.getActivePackageNameForApexModuleName(moduleName)) .isEqualTo(TEST_APEX_PKG); diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java index e4ee4d064724..fdf9354747a0 100644 --- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java @@ -266,6 +266,11 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { public void sendIntentSender(IntentSender intent) { // Placeholder for spying. } + + @Override + public String getPackageName() { + return SYSTEM_PACKAGE_NAME; + } } /** ShortcutService with injection override methods. */ @@ -704,6 +709,7 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { protected UriPermissionOwner mUriPermissionOwner; + protected static final String SYSTEM_PACKAGE_NAME = "android"; protected static final String CALLING_PACKAGE_1 = "com.android.test.1"; protected static final int CALLING_UID_1 = 10001; diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/PackageParserLegacyCoreTest.java b/services/tests/servicestests/src/com/android/server/pm/parsing/PackageParserLegacyCoreTest.java index 07cca0ca6ba0..4d1c58d2c274 100644 --- a/services/tests/servicestests/src/com/android/server/pm/parsing/PackageParserLegacyCoreTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/parsing/PackageParserLegacyCoreTest.java @@ -610,7 +610,7 @@ public class PackageParserLegacyCoreTest { assertNotNull(pi.signingInfo); assertTrue(pi.signingInfo.getApkContentsSigners().length > 0); assertTrue(pi.isApex); - assertTrue((pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0); + assertTrue((pi.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0); assertTrue((pi.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) != 0); } diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java index fbcad62988be..ae4ff86320e6 100644 --- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java @@ -913,27 +913,6 @@ public class PowerManagerServiceTest { } @Test - public void testInattentiveSleep_dreamEnds_goesToSleepAfterTimeout() { - setMinimumScreenOffTimeoutConfig(5); - setAttentiveTimeout(30000); - createService(); - startSystem(); - - advanceTime(10000); - forceDream(); - advanceTime(10000); - final String pkg = mContextSpy.getOpPackageName(); - mService.getBinderServiceInstance().wakeUp(mClock.now(), - PowerManager.WAKE_REASON_DREAM_FINISHED, "PowerManagerServiceTest:DREAM_FINISHED", - pkg); - advanceTime(10001); - - assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); - assertThat(mService.getBinderServiceInstance().getLastSleepReason()).isEqualTo( - PowerManager.GO_TO_SLEEP_REASON_INATTENTIVE); - } - - @Test public void testInattentiveSleep_goesToSleepWithWakeLock() { final String pkg = mContextSpy.getOpPackageName(); final Binder token = new Binder(); @@ -956,6 +935,27 @@ public class PowerManagerServiceTest { } @Test + public void testInattentiveSleep_dreamEnds_goesToSleepAfterTimeout() { + setMinimumScreenOffTimeoutConfig(5); + setAttentiveTimeout(30000); + createService(); + startSystem(); + + advanceTime(10000); + forceDream(); + advanceTime(10000); + final String pkg = mContextSpy.getOpPackageName(); + mService.getBinderServiceInstance().wakeUp(mClock.now(), + PowerManager.WAKE_REASON_DREAM_FINISHED, "PowerManagerServiceTest:DREAM_FINISHED", + pkg); + advanceTime(10001); + + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); + assertThat(mService.getBinderServiceInstance().getLastSleepReason()).isEqualTo( + PowerManager.GO_TO_SLEEP_REASON_INATTENTIVE); + } + + @Test public void testInattentiveSleep_wakeLockOnAfterRelease_inattentiveSleepTimeoutNotAffected() { final DisplayInfo info = new DisplayInfo(); info.displayGroupId = Display.DEFAULT_DISPLAY_GROUP; diff --git a/services/tests/uiservicestests/AndroidManifest.xml b/services/tests/uiservicestests/AndroidManifest.xml index 767857bf2de8..e8e3a8f84f21 100644 --- a/services/tests/uiservicestests/AndroidManifest.xml +++ b/services/tests/uiservicestests/AndroidManifest.xml @@ -33,6 +33,7 @@ <uses-permission android:name="android.permission.OBSERVE_ROLE_HOLDERS" /> <uses-permission android:name="android.permission.GET_INTENT_SENDER_INTENT"/> <uses-permission android:name="android.permission.WRITE_DEVICE_CONFIG" /> + <uses-permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE" /> <application android:debuggable="true"> <uses-library android:name="android.test.runner" /> diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java index 2f054b004d42..8ba9af0d85d0 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java @@ -840,6 +840,156 @@ public class ManagedServicesTest extends UiServiceTestCase { } @Test + public void reregisterService_checksAppIsApproved_pkg() throws Exception { + Context context = mock(Context.class); + PackageManager pm = mock(PackageManager.class); + ApplicationInfo ai = new ApplicationInfo(); + ai.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT; + + when(context.getPackageName()).thenReturn(mContext.getPackageName()); + when(context.getUserId()).thenReturn(mContext.getUserId()); + when(context.getPackageManager()).thenReturn(pm); + when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(ai); + + ManagedServices service = new TestManagedServices(context, mLock, mUserProfiles, mIpm, + APPROVAL_BY_PACKAGE); + ComponentName cn = ComponentName.unflattenFromString("a/a"); + + when(context.bindServiceAsUser(any(), any(), anyInt(), any())).thenAnswer(invocation -> { + Object[] args = invocation.getArguments(); + ServiceConnection sc = (ServiceConnection) args[1]; + sc.onServiceConnected(cn, mock(IBinder.class)); + return true; + }); + + service.addApprovedList("a", 0, true); + + service.reregisterService(cn, 0); + + assertTrue(service.isBound(cn, 0)); + } + + @Test + public void reregisterService_checksAppIsApproved_pkg_secondary() throws Exception { + Context context = mock(Context.class); + PackageManager pm = mock(PackageManager.class); + ApplicationInfo ai = new ApplicationInfo(); + ai.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT; + + when(context.getPackageName()).thenReturn(mContext.getPackageName()); + when(context.getUserId()).thenReturn(mContext.getUserId()); + when(context.getPackageManager()).thenReturn(pm); + when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(ai); + + ManagedServices service = new TestManagedServices(context, mLock, mUserProfiles, mIpm, + APPROVAL_BY_PACKAGE); + ComponentName cn = ComponentName.unflattenFromString("a/a"); + + when(context.bindServiceAsUser(any(), any(), anyInt(), any())).thenAnswer(invocation -> { + Object[] args = invocation.getArguments(); + ServiceConnection sc = (ServiceConnection) args[1]; + sc.onServiceConnected(cn, mock(IBinder.class)); + return true; + }); + + service.addApprovedList("a", 0, false); + + service.reregisterService(cn, 0); + + assertTrue(service.isBound(cn, 0)); + } + + @Test + public void reregisterService_checksAppIsApproved_cn() throws Exception { + Context context = mock(Context.class); + PackageManager pm = mock(PackageManager.class); + ApplicationInfo ai = new ApplicationInfo(); + ai.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT; + + when(context.getPackageName()).thenReturn(mContext.getPackageName()); + when(context.getUserId()).thenReturn(mContext.getUserId()); + when(context.getPackageManager()).thenReturn(pm); + when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(ai); + + ManagedServices service = new TestManagedServices(context, mLock, mUserProfiles, mIpm, + APPROVAL_BY_COMPONENT); + ComponentName cn = ComponentName.unflattenFromString("a/a"); + + when(context.bindServiceAsUser(any(), any(), anyInt(), any())).thenAnswer(invocation -> { + Object[] args = invocation.getArguments(); + ServiceConnection sc = (ServiceConnection) args[1]; + sc.onServiceConnected(cn, mock(IBinder.class)); + return true; + }); + + service.addApprovedList("a/a", 0, true); + + service.reregisterService(cn, 0); + + assertTrue(service.isBound(cn, 0)); + } + + @Test + public void reregisterService_checksAppIsApproved_cn_secondary() throws Exception { + Context context = mock(Context.class); + PackageManager pm = mock(PackageManager.class); + ApplicationInfo ai = new ApplicationInfo(); + ai.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT; + + when(context.getPackageName()).thenReturn(mContext.getPackageName()); + when(context.getUserId()).thenReturn(mContext.getUserId()); + when(context.getPackageManager()).thenReturn(pm); + when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(ai); + + ManagedServices service = new TestManagedServices(context, mLock, mUserProfiles, mIpm, + APPROVAL_BY_COMPONENT); + ComponentName cn = ComponentName.unflattenFromString("a/a"); + + when(context.bindServiceAsUser(any(), any(), anyInt(), any())).thenAnswer(invocation -> { + Object[] args = invocation.getArguments(); + ServiceConnection sc = (ServiceConnection) args[1]; + sc.onServiceConnected(cn, mock(IBinder.class)); + return true; + }); + + service.addApprovedList("a/a", 0, false); + + service.reregisterService(cn, 0); + + assertTrue(service.isBound(cn, 0)); + } + + @Test + public void reregisterService_checksAppIsNotApproved_cn_secondary() throws Exception { + Context context = mock(Context.class); + PackageManager pm = mock(PackageManager.class); + ApplicationInfo ai = new ApplicationInfo(); + ai.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT; + + when(context.getPackageName()).thenReturn(mContext.getPackageName()); + when(context.getUserId()).thenReturn(mContext.getUserId()); + when(context.getPackageManager()).thenReturn(pm); + when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(ai); + + ManagedServices service = new TestManagedServices(context, mLock, mUserProfiles, mIpm, + APPROVAL_BY_COMPONENT); + ComponentName cn = ComponentName.unflattenFromString("a/a"); + + when(context.bindServiceAsUser(any(), any(), anyInt(), any())).thenAnswer(invocation -> { + Object[] args = invocation.getArguments(); + ServiceConnection sc = (ServiceConnection) args[1]; + sc.onServiceConnected(cn, mock(IBinder.class)); + return true; + }); + + service.addApprovedList("b/b", 0, false); + + service.reregisterService(cn, 0); + + assertFalse(service.isBound(cn, 0)); + } + + @Test public void unbindOtherUserServices() throws PackageManager.NameNotFoundException { Context context = mock(Context.class); PackageManager pm = mock(PackageManager.class); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java index bd7186e74354..a7d18eeba058 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java @@ -126,7 +126,7 @@ public class NotificationHistoryDatabaseTest extends UiServiceTestCase { when(file.getAbsolutePath()).thenReturn(String.valueOf(i)); AtomicFile af = new AtomicFile(file); expectedFiles.add(af); - mDataBase.mHistoryFiles.addLast(af); + mDataBase.mHistoryFiles.add(af); } cal.add(Calendar.DATE, -1 * retainDays); @@ -136,7 +136,7 @@ public class NotificationHistoryDatabaseTest extends UiServiceTestCase { when(file.getName()).thenReturn(String.valueOf(cal.getTimeInMillis() - i)); when(file.getAbsolutePath()).thenReturn(String.valueOf(cal.getTimeInMillis() - i)); AtomicFile af = new AtomicFile(file); - mDataBase.mHistoryFiles.addLast(af); + mDataBase.mHistoryFiles.add(af); } // back to today; trim everything a day + old @@ -162,7 +162,7 @@ public class NotificationHistoryDatabaseTest extends UiServiceTestCase { when(file.getName()).thenReturn(i + ".bak"); when(file.getAbsolutePath()).thenReturn(i + ".bak"); AtomicFile af = new AtomicFile(file); - mDataBase.mHistoryFiles.addLast(af); + mDataBase.mHistoryFiles.add(af); } // trim everything a day+ old @@ -224,7 +224,7 @@ public class NotificationHistoryDatabaseTest extends UiServiceTestCase { public void testReadNotificationHistory_readsAllFiles() throws Exception { for (long i = 10; i >= 5; i--) { AtomicFile af = mock(AtomicFile.class); - mDataBase.mHistoryFiles.addLast(af); + mDataBase.mHistoryFiles.add(af); } mDataBase.readNotificationHistory(); @@ -248,11 +248,11 @@ public class NotificationHistoryDatabaseTest extends UiServiceTestCase { public void testReadNotificationHistory_withNumFilterDoesNotReadExtraFiles() throws Exception { AtomicFile af = mock(AtomicFile.class); when(af.getBaseFile()).thenReturn(new File(mRootDir, "af")); - mDataBase.mHistoryFiles.addLast(af); + mDataBase.mHistoryFiles.add(af); AtomicFile af2 = mock(AtomicFile.class); when(af2.getBaseFile()).thenReturn(new File(mRootDir, "af2")); - mDataBase.mHistoryFiles.addLast(af2); + mDataBase.mHistoryFiles.add(af2); mDataBase.readNotificationHistory(null, null, 0); @@ -269,7 +269,7 @@ public class NotificationHistoryDatabaseTest extends UiServiceTestCase { AtomicFile af = mock(AtomicFile.class); when(af.getBaseFile()).thenReturn(new File(mRootDir, "af")); - mDataBase.mHistoryFiles.addLast(af); + mDataBase.mHistoryFiles.add(af); when(nh.removeNotificationFromWrite("pkg", 123)).thenReturn(true); @@ -292,7 +292,7 @@ public class NotificationHistoryDatabaseTest extends UiServiceTestCase { AtomicFile af = mock(AtomicFile.class); when(af.getBaseFile()).thenReturn(new File(mRootDir, "af")); - mDataBase.mHistoryFiles.addLast(af); + mDataBase.mHistoryFiles.add(af); when(nh.removeNotificationFromWrite("pkg", 123)).thenReturn(false); @@ -315,7 +315,7 @@ public class NotificationHistoryDatabaseTest extends UiServiceTestCase { AtomicFile af = mock(AtomicFile.class); when(af.getBaseFile()).thenReturn(new File(mRootDir, "af")); - mDataBase.mHistoryFiles.addLast(af); + mDataBase.mHistoryFiles.add(af); when(nh.removeConversationsFromWrite("pkg", Set.of("convo", "another"))).thenReturn(true); @@ -338,7 +338,7 @@ public class NotificationHistoryDatabaseTest extends UiServiceTestCase { AtomicFile af = mock(AtomicFile.class); when(af.getBaseFile()).thenReturn(new File(mRootDir, "af")); - mDataBase.mHistoryFiles.addLast(af); + mDataBase.mHistoryFiles.add(af); when(nh.removeConversationsFromWrite("pkg", Set.of("convo"))).thenReturn(false); @@ -361,7 +361,7 @@ public class NotificationHistoryDatabaseTest extends UiServiceTestCase { AtomicFile af = mock(AtomicFile.class); when(af.getBaseFile()).thenReturn(new File(mRootDir, "af")); - mDataBase.mHistoryFiles.addLast(af); + mDataBase.mHistoryFiles.add(af); when(nh.removeChannelFromWrite("pkg", "channel")).thenReturn(true); @@ -384,7 +384,7 @@ public class NotificationHistoryDatabaseTest extends UiServiceTestCase { AtomicFile af = mock(AtomicFile.class); when(af.getBaseFile()).thenReturn(new File(mRootDir, "af")); - mDataBase.mHistoryFiles.addLast(af); + mDataBase.mHistoryFiles.add(af); when(nh.removeChannelFromWrite("pkg", "channel")).thenReturn(false); @@ -424,7 +424,7 @@ public class NotificationHistoryDatabaseTest extends UiServiceTestCase { for (int i = 0; i < 5; i++) { AtomicFile af = mock(AtomicFile.class); when(af.getBaseFile()).thenReturn(new File(mRootDir, "af" + i)); - mDataBase.mHistoryFiles.addLast(af); + mDataBase.mHistoryFiles.add(af); } // Baseline size of history files assertThat(mDataBase.mHistoryFiles.size()).isEqualTo(5); @@ -440,7 +440,7 @@ public class NotificationHistoryDatabaseTest extends UiServiceTestCase { for (int i = 0; i < 5; i++) { AtomicFile af = mock(AtomicFile.class); when(af.getBaseFile()).thenReturn(new File(mRootDir, "af" + i)); - mDataBase.mHistoryFiles.addLast(af); + mDataBase.mHistoryFiles.add(af); } // Baseline size of history files assertThat(mDataBase.mHistoryFiles.size()).isEqualTo(5); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java index f4b9e258f7e0..68551d9813d3 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java @@ -28,24 +28,37 @@ 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.eq; import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.reset; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.INotificationManager; +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; import android.content.ComponentName; +import android.content.Context; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.pm.ServiceInfo; import android.content.pm.VersionedPackage; import android.os.Bundle; +import android.os.IBinder; +import android.os.IInterface; import android.os.UserHandle; import android.service.notification.NotificationListenerFilter; import android.service.notification.NotificationListenerService; +import android.service.notification.NotificationStats; +import android.service.notification.NotificationRankingUpdate; +import android.service.notification.StatusBarNotification; import android.testing.TestableContext; import android.util.ArraySet; import android.util.Pair; @@ -55,15 +68,19 @@ import android.util.Xml; import com.android.server.UiServiceTestCase; +import com.google.common.collect.ImmutableList; + import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.mockito.internal.util.reflection.FieldSetter; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.util.List; public class NotificationListenersTest extends UiServiceTestCase { @@ -388,4 +405,96 @@ public class NotificationListenersTest extends UiServiceTestCase { verify(mContext).sendBroadcastAsUser( any(), eq(UserHandle.of(userId)), nullable(String.class)); } + + @Test + public void testNotifyPostedLockedInLockdownMode() { + NotificationRecord r = mock(NotificationRecord.class); + NotificationRecord old = mock(NotificationRecord.class); + + // before the lockdown mode + when(mNm.isInLockDownMode()).thenReturn(false); + mListeners.notifyPostedLocked(r, old, true); + mListeners.notifyPostedLocked(r, old, false); + verify(r, atLeast(2)).getSbn(); + + // in the lockdown mode + reset(r); + reset(old); + when(mNm.isInLockDownMode()).thenReturn(true); + mListeners.notifyPostedLocked(r, old, true); + mListeners.notifyPostedLocked(r, old, false); + verify(r, never()).getSbn(); + } + + @Test + public void testnotifyRankingUpdateLockedInLockdownMode() { + List chn = mock(List.class); + + // before the lockdown mode + when(mNm.isInLockDownMode()).thenReturn(false); + mListeners.notifyRankingUpdateLocked(chn); + verify(chn, atLeast(1)).size(); + + // in the lockdown mode + reset(chn); + when(mNm.isInLockDownMode()).thenReturn(true); + mListeners.notifyRankingUpdateLocked(chn); + verify(chn, never()).size(); + } + + @Test + public void testNotifyRemovedLockedInLockdownMode() throws NoSuchFieldException { + NotificationRecord r = mock(NotificationRecord.class); + NotificationStats rs = mock(NotificationStats.class); + StatusBarNotification sbn = mock(StatusBarNotification.class); + FieldSetter.setField(mNm, + NotificationManagerService.class.getDeclaredField("mHandler"), + mock(NotificationManagerService.WorkerHandler.class)); + + // before the lockdown mode + when(mNm.isInLockDownMode()).thenReturn(false); + when(r.getSbn()).thenReturn(sbn); + mListeners.notifyRemovedLocked(r, 0, rs); + mListeners.notifyRemovedLocked(r, 0, rs); + verify(r, atLeast(2)).getSbn(); + + // in the lockdown mode + reset(r); + reset(rs); + when(mNm.isInLockDownMode()).thenReturn(true); + when(r.getSbn()).thenReturn(sbn); + mListeners.notifyRemovedLocked(r, 0, rs); + mListeners.notifyRemovedLocked(r, 0, rs); + verify(r, never()).getSbn(); + } + + @Test + public void testImplicitGrant() { + String pkg = "pkg"; + int uid = 9; + NotificationChannel channel = new NotificationChannel("id", "name", + NotificationManager.IMPORTANCE_HIGH); + Notification.Builder nb = new Notification.Builder(mContext, channel.getId()) + .setContentTitle("foo") + .setSmallIcon(android.R.drawable.sym_def_app_icon) + .setTimeoutAfter(1); + + StatusBarNotification sbn = new StatusBarNotification(pkg, pkg, 8, "tag", uid, 0, + nb.build(), UserHandle.getUserHandleForUid(uid), null, 0); + NotificationRecord r = new NotificationRecord(mContext, sbn, channel); + + ManagedServices.ManagedServiceInfo info = mListeners.new ManagedServiceInfo( + null, new ComponentName("a", "a"), sbn.getUserId(), false, null, 33, 33); + List<ManagedServices.ManagedServiceInfo> services = ImmutableList.of(info); + when(mListeners.getServices()).thenReturn(services); + + when(mNm.isVisibleToListener(any(), anyInt(), any())).thenReturn(true); + when(mNm.makeRankingUpdateLocked(info)).thenReturn(mock(NotificationRankingUpdate.class)); + mNm.mPackageManagerInternal = mPmi; + + mListeners.notifyPostedLocked(r, null); + + verify(mPmi).grantImplicitAccess(sbn.getUserId(), null, UserHandle.getAppId(33), + sbn.getUid(), false, false); + } } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index b987c692bddb..c29748bec3a5 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -63,10 +63,13 @@ import static android.service.notification.Adjustment.KEY_USER_SENTIMENT; import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ALERTING; import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_CONVERSATIONS; import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ONGOING; +import static android.service.notification.NotificationListenerService.REASON_LOCKDOWN; import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE; import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL; import static android.view.WindowManager.LayoutParams.TYPE_TOAST; +import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN; + import static com.google.common.truth.Truth.assertThat; import static junit.framework.Assert.assertEquals; @@ -352,6 +355,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { MultiRateLimiter mToastRateLimiter; BroadcastReceiver mPackageIntentReceiver; NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake(); + TestableNotificationManagerService.StrongAuthTrackerFake mStrongAuthTracker; private InstanceIdSequence mNotificationInstanceIdSequence = new InstanceIdSequenceFake( 1 << 30); @Mock @@ -508,6 +512,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mService.setAudioManager(mAudioManager); + mStrongAuthTracker = mService.new StrongAuthTrackerFake(mContext); + mService.setStrongAuthTracker(mStrongAuthTracker); + mShortcutHelper = mService.getShortcutHelper(); mShortcutHelper.setLauncherApps(mLauncherApps); mShortcutHelper.setShortcutServiceInternal(mShortcutServiceInternal); @@ -9247,4 +9254,44 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { // make sure the summary was removed and not re-posted assertThat(mService.getNotificationRecordCount()).isEqualTo(0); } + + @Test + public void testStrongAuthTracker_isInLockDownMode() { + mStrongAuthTracker.setGetStrongAuthForUserReturnValue( + STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN); + mStrongAuthTracker.onStrongAuthRequiredChanged(mContext.getUserId()); + assertTrue(mStrongAuthTracker.isInLockDownMode()); + mStrongAuthTracker.setGetStrongAuthForUserReturnValue(0); + mStrongAuthTracker.onStrongAuthRequiredChanged(mContext.getUserId()); + assertFalse(mStrongAuthTracker.isInLockDownMode()); + } + + @Test + public void testCancelAndPostNotificationsWhenEnterAndExitLockDownMode() { + // post 2 notifications from 2 packages + NotificationRecord pkgA = new NotificationRecord(mContext, + generateSbn("a", 1000, 9, 0), mTestNotificationChannel); + mService.addNotification(pkgA); + NotificationRecord pkgB = new NotificationRecord(mContext, + generateSbn("b", 1001, 9, 0), mTestNotificationChannel); + mService.addNotification(pkgB); + + // when entering the lockdown mode, cancel the 2 notifications. + mStrongAuthTracker.setGetStrongAuthForUserReturnValue( + STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN); + mStrongAuthTracker.onStrongAuthRequiredChanged(mContext.getUserId()); + assertTrue(mStrongAuthTracker.isInLockDownMode()); + + // the notifyRemovedLocked function is called twice due to REASON_LOCKDOWN. + ArgumentCaptor<Integer> captor = ArgumentCaptor.forClass(Integer.class); + verify(mListeners, times(2)).notifyRemovedLocked(any(), captor.capture(), any()); + assertEquals(REASON_LOCKDOWN, captor.getValue().intValue()); + + // exit lockdown mode. + mStrongAuthTracker.setGetStrongAuthForUserReturnValue(0); + mStrongAuthTracker.onStrongAuthRequiredChanged(mContext.getUserId()); + + // the notifyPostedLocked function is called twice. + verify(mListeners, times(2)).notifyPostedLocked(any(), any()); + } } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/TestableNotificationManagerService.java b/services/tests/uiservicestests/src/com/android/server/notification/TestableNotificationManagerService.java index bde048569e53..4ed7d35a097f 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/TestableNotificationManagerService.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/TestableNotificationManagerService.java @@ -113,4 +113,20 @@ public class TestableNotificationManagerService extends NotificationManagerServi protected void doChannelWarningToast(int uid, CharSequence toastText) { mChannelToastsSent.add(uid); } + + public class StrongAuthTrackerFake extends NotificationManagerService.StrongAuthTracker { + private int mGetStrongAuthForUserReturnValue = 0; + StrongAuthTrackerFake(Context context) { + super(context); + } + + public void setGetStrongAuthForUserReturnValue(int val) { + mGetStrongAuthForUserReturnValue = val; + } + + @Override + public int getStrongAuthForUser(int userId) { + return mGetStrongAuthForUserReturnValue; + } + } } diff --git a/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java index dd0c162d8467..a917c57446a9 100644 --- a/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java @@ -122,8 +122,7 @@ public class SliceManagerServiceTest extends UiServiceTestCase { when(mContextSpy.checkPermission("perm2", Process.myPid(), Process.myUid())) .thenReturn(PERMISSION_GRANTED); mService.checkSlicePermission(TEST_URI, mContext.getPackageName(), - mContext.getPackageName(), Process.myPid(), - Process.myUid(), testPerms); + Process.myPid(), Process.myUid(), testPerms); verify(mContextSpy).checkPermission(eq("perm1"), eq(Process.myPid()), eq(Process.myUid())); verify(mContextSpy).checkPermission(eq("perm2"), eq(Process.myPid()), eq(Process.myUid())); @@ -148,7 +147,7 @@ public class SliceManagerServiceTest extends UiServiceTestCase { private void grantSlicePermission() { doReturn(PERMISSION_GRANTED).when(mService).checkSlicePermission( - eq(TEST_URI), anyString(), anyString(), anyInt(), anyInt(), any()); + eq(TEST_URI), anyString(), anyInt(), anyInt(), any()); doReturn(PERMISSION_GRANTED).when(mService).checkAccess( anyString(), eq(TEST_URI), anyInt(), anyInt()); } diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java index 716612c70aef..75ecfd870eb2 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java @@ -21,6 +21,7 @@ import static android.app.ActivityManager.START_TASK_TO_FRONT; import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.never; import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset; @@ -34,6 +35,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.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.eq; @@ -284,10 +286,14 @@ public class ActivityTaskSupervisorTests extends WindowTestsBase { .setCreateActivity(true).build().getTopMostActivity(); activity2.getTask().setResumedActivity(activity2, "test"); - mAtm.mAmInternal.deletePendingTopUid(activity1.getUid(), Long.MAX_VALUE); + final int[] pendingTopUid = new int[1]; + doAnswer(invocation -> { + pendingTopUid[0] = invocation.getArgument(0); + return null; + }).when(mAtm.mAmInternal).addPendingTopUid(anyInt(), anyInt(), any()); clearInvocations(mAtm); activity1.moveFocusableActivityToTop("test"); - assertTrue(mAtm.mAmInternal.isPendingTopUid(activity1.getUid())); + assertEquals(activity1.getUid(), pendingTopUid[0]); verify(mAtm).updateOomAdj(); } diff --git a/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java b/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java index 3beb7f2049df..88c7017e9942 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java @@ -283,6 +283,21 @@ public class DimmerTests extends WindowTestsBase { verify(mTransaction).remove(dimLayer); } + @Test + public void testDimmerWithBlurUpdatesTransaction() { + TestWindowContainer child = new TestWindowContainer(mWm); + mHost.addChild(child, 0); + + final int blurRadius = 50; + mDimmer.dimBelow(mTransaction, child, 0, blurRadius); + SurfaceControl dimLayer = getDimLayer(); + + assertNotNull("Dimmer should have created a surface", dimLayer); + + verify(mTransaction).setBackgroundBlurRadius(dimLayer, blurRadius); + verify(mTransaction).setRelativeLayer(dimLayer, child.mControl, -1); + } + private SurfaceControl getDimLayer() { return mDimmer.mDimState.mDimLayer; } 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 56244cb92a97..ccafbb2f2c5d 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -22,6 +22,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.content.pm.ActivityInfo.FLAG_SHOW_WHEN_LOCKED; +import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND; 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; @@ -1095,6 +1096,25 @@ public class DisplayContentTests extends WindowTestsBase { } @Test + public void testOrientationBehind() { + final ActivityRecord prev = new ActivityBuilder(mAtm).setCreateTask(true) + .setScreenOrientation(getRotatedOrientation(mDisplayContent)).build(); + prev.mVisibleRequested = false; + final ActivityRecord top = new ActivityBuilder(mAtm).setCreateTask(true) + .setScreenOrientation(SCREEN_ORIENTATION_BEHIND).build(); + assertNotEquals(WindowConfiguration.ROTATION_UNDEFINED, + mDisplayContent.rotationForActivityInDifferentOrientation(top)); + + mDisplayContent.requestTransitionAndLegacyPrepare(WindowManager.TRANSIT_OPEN, 0); + top.setVisibility(true); + mDisplayContent.updateOrientation(); + // The top uses "behind", so the orientation is decided by the previous. + assertEquals(prev, mDisplayContent.getLastOrientationSource()); + // The top will use the rotation from "prev" with fixed rotation. + assertTrue(top.hasFixedRotationTransform()); + } + + @Test public void testFixedToUserRotationChanged() { final DisplayContent dc = createNewDisplay(); dc.getDisplayRotation().setFixedToUserRotation( @@ -1652,8 +1672,7 @@ public class DisplayContentTests extends WindowTestsBase { // The condition should reject using fixed rotation because the resumed client in real case // might get display info immediately. And the fixed rotation adjustments haven't arrived // client side so the info may be inconsistent with the requested orientation. - verify(mDisplayContent).handleTopActivityLaunchingInDifferentOrientation(eq(app), - eq(true) /* checkOpening */); + verify(mDisplayContent).updateOrientation(eq(app), anyBoolean()); assertFalse(app.isFixedRotationTransforming()); assertFalse(mDisplayContent.hasTopFixedRotationLaunchingApp()); } 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 8ef9ada8995f..a3b881c8b270 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java @@ -657,7 +657,7 @@ public class RootWindowContainerTests extends WindowTestsBase { doReturn(true).when(mRootWindowContainer).resumeHomeActivity(any(), any(), any()); - mAtm.setBooted(true); + setBooted(mAtm); // Trigger resume on all displays mRootWindowContainer.resumeFocusedTasksTopActivities(); @@ -685,7 +685,7 @@ public class RootWindowContainerTests extends WindowTestsBase { doReturn(true).when(mRootWindowContainer).resumeHomeActivity(any(), any(), any()); - mAtm.setBooted(true); + setBooted(mAtm); // Trigger resume on all displays mRootWindowContainer.resumeFocusedTasksTopActivities(); @@ -771,17 +771,10 @@ public class RootWindowContainerTests extends WindowTestsBase { @Test public void testNotStartHomeBeforeBoot() { final int displayId = 1; - final boolean isBooting = mAtm.mAmInternal.isBooting(); - final boolean isBooted = mAtm.mAmInternal.isBooted(); - try { - mAtm.mAmInternal.setBooting(false); - mAtm.mAmInternal.setBooted(false); - mRootWindowContainer.onDisplayAdded(displayId); - verify(mRootWindowContainer, never()).startHomeOnDisplay(anyInt(), any(), anyInt()); - } finally { - mAtm.mAmInternal.setBooting(isBooting); - mAtm.mAmInternal.setBooted(isBooted); - } + doReturn(false).when(mAtm).isBooting(); + doReturn(false).when(mAtm).isBooted(); + mRootWindowContainer.onDisplayAdded(displayId); + verify(mRootWindowContainer, never()).startHomeOnDisplay(anyInt(), any(), anyInt()); } /** diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java index dc9a62554fdb..55cc238e1766 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java +++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java @@ -66,7 +66,6 @@ import android.os.UserHandle; import android.provider.DeviceConfig; import android.util.Log; import android.view.InputChannel; -import android.view.Surface; import android.view.SurfaceControl; import com.android.dx.mockito.inline.extended.StaticMockitoSession; @@ -77,7 +76,6 @@ import com.android.server.LockGuard; import com.android.server.UiThread; import com.android.server.Watchdog; import com.android.server.am.ActivityManagerService; -import com.android.server.appop.AppOpsService; import com.android.server.display.color.ColorDisplayService; import com.android.server.firewall.IntentFirewall; import com.android.server.input.InputManagerService; @@ -94,10 +92,8 @@ import org.mockito.MockSettings; import org.mockito.Mockito; import org.mockito.quality.Strictness; -import java.io.File; import java.util.ArrayList; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Supplier; /** * JUnit test rule to correctly setting up system services like {@link WindowManagerService} @@ -125,13 +121,11 @@ public class SystemServicesTestRule implements TestRule { private Description mDescription; private Context mContext; private StaticMockitoSession mMockitoSession; - private ActivityManagerService mAmService; private ActivityTaskManagerService mAtmService; private WindowManagerService mWmService; private WindowState.PowerManagerWrapper mPowerManagerWrapper; private InputManagerService mImService; private InputChannel mInputChannel; - private Supplier<Surface> mSurfaceFactory = () -> mock(Surface.class); /** * Spied {@link SurfaceControl.Transaction} class than can be used to verify calls. */ @@ -289,29 +283,9 @@ public class SystemServicesTestRule implements TestRule { } private void setUpActivityTaskManagerService() { - // ActivityManagerService - mAmService = new ActivityManagerService(new AMTestInjector(mContext), null /* thread */); - spyOn(mAmService); - doReturn(mock(IPackageManager.class)).when(mAmService).getPackageManager(); - doNothing().when(mAmService).grantImplicitAccess( - anyInt(), any(), anyInt(), anyInt()); - // ActivityManagerInternal - final ActivityManagerInternal amInternal = mAmService.mInternal; - spyOn(amInternal); - doNothing().when(amInternal).trimApplications(); - doNothing().when(amInternal).scheduleAppGcs(); - doNothing().when(amInternal).updateCpuStats(); - doNothing().when(amInternal).updateOomAdj(); - doNothing().when(amInternal).updateBatteryStats(any(), anyInt(), anyInt(), anyBoolean()); - doNothing().when(amInternal).updateActivityUsageStats( - any(), anyInt(), anyInt(), any(), any()); - doNothing().when(amInternal).startProcess( - any(), any(), anyBoolean(), anyBoolean(), any(), any()); - doNothing().when(amInternal).updateOomLevelsForDisplay(anyInt()); - doNothing().when(amInternal).broadcastGlobalConfigurationChanged(anyInt(), anyBoolean()); - doNothing().when(amInternal).cleanUpServices(anyInt(), any(), any()); - doNothing().when(amInternal).reportCurKeyguardUsageEvent(anyBoolean()); + final ActivityManagerInternal amInternal = + mock(ActivityManagerInternal.class, withSettings().stubOnly()); doReturn(UserHandle.USER_SYSTEM).when(amInternal).getCurrentUserId(); doReturn(TEST_USER_PROFILE_IDS).when(amInternal).getCurrentProfileIds(); doReturn(true).when(amInternal).isUserRunning(anyInt(), anyInt()); @@ -320,7 +294,9 @@ public class SystemServicesTestRule implements TestRule { doReturn(false).when(amInternal).isActivityStartsLoggingEnabled(); LocalServices.addService(ActivityManagerInternal.class, amInternal); - mAtmService = new TestActivityTaskManagerService(mContext, mAmService); + final ActivityManagerService amService = + mock(ActivityManagerService.class, withSettings().stubOnly()); + mAtmService = new TestActivityTaskManagerService(mContext, amService); LocalServices.addService(ActivityTaskManagerInternal.class, mAtmService.getAtmInternal()); } @@ -332,9 +308,9 @@ public class SystemServicesTestRule implements TestRule { // Suppress StrictMode violation (DisplayWindowSettings) to avoid log flood. DisplayThread.getHandler().post(StrictMode::allowThreadDiskWritesMask); mWmService = WindowManagerService.main( - mContext, mImService, false, false, wmPolicy, mAtmService, + mContext, mImService, false, wmPolicy, mAtmService, testDisplayWindowSettingsProvider, StubTransaction::new, - () -> mSurfaceFactory.get(), (unused) -> new MockSurfaceControlBuilder()); + (unused) -> new MockSurfaceControlBuilder()); spyOn(mWmService); spyOn(mWmService.mRoot); // Invoked during {@link ActivityStack} creation. @@ -355,7 +331,7 @@ public class SystemServicesTestRule implements TestRule { null, null, mTransaction, mWmService.mPowerManagerInternal); mWmService.onInitReady(); - mAmService.setWindowManager(mWmService); + mAtmService.setWindowManager(mWmService); mWmService.mDisplayEnabled = true; mWmService.mDisplayReady = true; // Set configuration for default display @@ -454,10 +430,6 @@ public class SystemServicesTestRule implements TestRule { .spiedInstance(sWakeLock).stubOnly()); } - void setSurfaceFactory(Supplier<Surface> factory) { - mSurfaceFactory = factory; - } - void cleanupWindowManagerHandlers() { final WindowManagerService wm = getWindowManagerService(); if (wm == null) { @@ -618,32 +590,4 @@ public class SystemServicesTestRule implements TestRule { doReturn(true).when(controller).checkKeyguardVisibility(any()); } } - - // TODO: Can we just mock this? - private static class AMTestInjector extends ActivityManagerService.Injector { - - AMTestInjector(Context context) { - super(context); - } - - @Override - public Context getContext() { - return getInstrumentation().getTargetContext(); - } - - @Override - public AppOpsService getAppOpsService(File file, Handler handler) { - return null; - } - - @Override - public Handler getUiHandler(ActivityManagerService service) { - return UiThread.getHandler(); - } - - @Override - public boolean isNetworkRestrictedForUid(int uid) { - return false; - } - } } 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 6c1c0865446e..9dedc850defc 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java @@ -955,6 +955,29 @@ public class TransitionTests extends WindowTestsBase { verify(snapshotController, times(1)).recordTaskSnapshot(eq(task1), eq(false)); } + @Test + public void testNotReadyPushPop() { + final TaskSnapshotController snapshotController = mock(TaskSnapshotController.class); + final TransitionController controller = new TransitionController(mAtm, snapshotController); + final ITransitionPlayer player = new ITransitionPlayer.Default(); + controller.registerTransitionPlayer(player, null /* appThread */); + final Transition openTransition = controller.createTransition(TRANSIT_OPEN); + + // Start out with task2 visible and set up a transition that closes task2 and opens task1 + final Task task1 = createTask(mDisplayContent); + openTransition.collectExistenceChange(task1); + + assertFalse(openTransition.allReady()); + + openTransition.setAllReady(); + + openTransition.deferTransitionReady(); + assertFalse(openTransition.allReady()); + + openTransition.continueTransitionReady(); + assertTrue(openTransition.allReady()); + } + private static void makeTaskOrganized(Task... tasks) { final ITaskOrganizer organizer = mock(ITaskOrganizer.class); for (Task t : tasks) { diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java index 2cb398204743..3bd9b6c7000a 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java @@ -516,6 +516,7 @@ final class HotwordDetectionConnection { if (mValidatingDspTrigger) { mValidatingDspTrigger = false; enforcePermissionsForDataDelivery(); + enforceExtraKeyphraseIdNotLeaked(result, recognitionEvent); externalCallback.onKeyphraseDetected(recognitionEvent, result); if (result != null) { Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(result) @@ -591,6 +592,7 @@ final class HotwordDetectionConnection { mValidatingDspTrigger = false; try { enforcePermissionsForDataDelivery(); + enforceExtraKeyphraseIdNotLeaked(result, recognitionEvent); } catch (SecurityException e) { HotwordMetricsLogger.writeKeyphraseTriggerEvent( mDetectorType, @@ -1143,6 +1145,19 @@ final class HotwordDetectionConnection { } } + private static void enforceExtraKeyphraseIdNotLeaked(HotwordDetectedResult result, + SoundTrigger.KeyphraseRecognitionEvent recognitionEvent) { + // verify the phrase ID in HotwordDetectedResult is not exposing extra phrases + // the DSP did not detect + for (SoundTrigger.KeyphraseRecognitionExtra keyphrase : recognitionEvent.keyphraseExtras) { + if (keyphrase.getKeyphraseId() == result.getHotwordPhraseId()) { + return; + } + } + throw new SecurityException("Ignoring #onDetected due to trusted service " + + "sharing a keyphrase ID which the DSP did not detect"); + } + private static final String OP_MESSAGE = "Providing hotword detection result to VoiceInteractionService"; }; diff --git a/telecomm/java/android/telecom/Logging/EventManager.java b/telecomm/java/android/telecom/Logging/EventManager.java index 1342038c6477..a74c0bb99549 100644 --- a/telecomm/java/android/telecom/Logging/EventManager.java +++ b/telecomm/java/android/telecom/Logging/EventManager.java @@ -180,7 +180,7 @@ public class EventManager { } } - private final List<Event> mEvents = Collections.synchronizedList(new LinkedList<>()); + private final List<Event> mEvents = Collections.synchronizedList(new ArrayList<>()); private final Loggable mRecordEntry; public EventRecord(Loggable recordEntry) { @@ -197,7 +197,7 @@ public class EventManager { } public List<Event> getEvents() { - return new LinkedList<>(mEvents); + return new ArrayList<>(mEvents); } public List<EventTiming> extractEventTimings() { @@ -205,7 +205,7 @@ public class EventManager { return Collections.emptyList(); } - LinkedList<EventTiming> result = new LinkedList<>(); + ArrayList<EventTiming> result = new ArrayList<>(); Map<String, PendingResponse> pendingResponses = new HashMap<>(); synchronized (mEvents) { for (Event event : mEvents) { diff --git a/telecomm/java/android/telecom/ParcelableCallAnalytics.java b/telecomm/java/android/telecom/ParcelableCallAnalytics.java index b8ad9e2fbe6c..ff87ab00ae8b 100644 --- a/telecomm/java/android/telecom/ParcelableCallAnalytics.java +++ b/telecomm/java/android/telecom/ParcelableCallAnalytics.java @@ -359,7 +359,7 @@ public class ParcelableCallAnalytics implements Parcelable { eventTimings = new ArrayList<>(); in.readTypedList(eventTimings, EventTiming.CREATOR); isVideoCall = readByteAsBoolean(in); - videoEvents = new LinkedList<>(); + videoEvents = new ArrayList<>(); in.readTypedList(videoEvents, VideoEvent.CREATOR); callSource = in.readInt(); } diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java index e0f5b2095190..0f7dde5a18d9 100644 --- a/telecomm/java/android/telecom/TelecomManager.java +++ b/telecomm/java/android/telecom/TelecomManager.java @@ -1179,7 +1179,7 @@ public class TelecomManager { if (service != null) { try { return service.getSimCallManager( - SubscriptionManager.getDefaultSubscriptionId()); + SubscriptionManager.getDefaultSubscriptionId(), mContext.getPackageName()); } catch (RemoteException e) { Log.e(TAG, "Error calling ITelecomService#getSimCallManager"); } @@ -1201,7 +1201,7 @@ public class TelecomManager { ITelecomService service = getTelecomService(); if (service != null) { try { - return service.getSimCallManager(subscriptionId); + return service.getSimCallManager(subscriptionId, mContext.getPackageName()); } catch (RemoteException e) { Log.e(TAG, "Error calling ITelecomService#getSimCallManager"); } @@ -1225,7 +1225,7 @@ public class TelecomManager { ITelecomService service = getTelecomService(); if (service != null) { try { - return service.getSimCallManagerForUser(userId); + return service.getSimCallManagerForUser(userId, mContext.getPackageName()); } catch (RemoteException e) { Log.e(TAG, "Error calling ITelecomService#getSimCallManagerForUser"); } @@ -1500,7 +1500,7 @@ public class TelecomManager { ITelecomService service = getTelecomService(); if (service != null) { try { - service.registerPhoneAccount(account); + service.registerPhoneAccount(account, mContext.getPackageName()); } catch (RemoteException e) { Log.e(TAG, "Error calling ITelecomService#registerPhoneAccount", e); } @@ -1516,7 +1516,7 @@ public class TelecomManager { ITelecomService service = getTelecomService(); if (service != null) { try { - service.unregisterPhoneAccount(accountHandle); + service.unregisterPhoneAccount(accountHandle, mContext.getPackageName()); } catch (RemoteException e) { Log.e(TAG, "Error calling ITelecomService#unregisterPhoneAccount", e); } @@ -1597,7 +1597,7 @@ public class TelecomManager { ITelecomService service = getTelecomService(); if (service != null) { try { - return service.getDefaultDialerPackage(); + return service.getDefaultDialerPackage(mContext.getPackageName()); } catch (RemoteException e) { Log.e(TAG, "RemoteException attempting to get the default dialer package name.", e); } @@ -1671,7 +1671,7 @@ public class TelecomManager { ITelecomService service = getTelecomService(); if (service != null) { try { - return service.getSystemDialerPackage(); + return service.getSystemDialerPackage(mContext.getPackageName()); } catch (RemoteException e) { Log.e(TAG, "RemoteException attempting to get the system dialer package name.", e); } @@ -2076,7 +2076,8 @@ public class TelecomManager { "acceptHandover for API > O-MR1"); return; } - service.addNewIncomingCall(phoneAccount, extras == null ? new Bundle() : extras); + service.addNewIncomingCall(phoneAccount, extras == null ? new Bundle() : extras, + mContext.getPackageName()); } catch (RemoteException e) { Log.e(TAG, "RemoteException adding a new incoming call: " + phoneAccount, e); } @@ -2118,7 +2119,8 @@ public class TelecomManager { if (service != null) { try { service.addNewIncomingConference( - phoneAccount, extras == null ? new Bundle() : extras); + phoneAccount, extras == null ? new Bundle() : extras, + mContext.getPackageName()); } catch (RemoteException e) { Log.e(TAG, "RemoteException adding a new incoming conference: " + phoneAccount, e); } @@ -2414,7 +2416,7 @@ public class TelecomManager { Intent result = null; if (service != null) { try { - result = service.createManageBlockedNumbersIntent(); + result = service.createManageBlockedNumbersIntent(mContext.getPackageName()); } catch (RemoteException e) { Log.e(TAG, "Error calling ITelecomService#createManageBlockedNumbersIntent", e); } @@ -2571,7 +2573,7 @@ public class TelecomManager { ITelecomService service = getTelecomService(); if (service != null) { try { - service.acceptHandover(srcAddr, videoState, destAcct); + service.acceptHandover(srcAddr, videoState, destAcct, mContext.getPackageName()); } catch (RemoteException e) { Log.e(TAG, "RemoteException acceptHandover: " + e); } diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl index 37403a806daf..101280abce85 100644 --- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl +++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl @@ -106,22 +106,22 @@ interface ITelecomService { /** * @see TelecomServiceImpl#getSimCallManager */ - PhoneAccountHandle getSimCallManager(int subId); + PhoneAccountHandle getSimCallManager(int subId, String callingPackage); /** * @see TelecomServiceImpl#getSimCallManagerForUser */ - PhoneAccountHandle getSimCallManagerForUser(int userId); + PhoneAccountHandle getSimCallManagerForUser(int userId, String callingPackage); /** * @see TelecomServiceImpl#registerPhoneAccount */ - void registerPhoneAccount(in PhoneAccount metadata); + void registerPhoneAccount(in PhoneAccount metadata, String callingPackage); /** * @see TelecomServiceImpl#unregisterPhoneAccount */ - void unregisterPhoneAccount(in PhoneAccountHandle account); + void unregisterPhoneAccount(in PhoneAccountHandle account, String callingPackage); /** * @see TelecomServiceImpl#clearAccounts @@ -154,7 +154,7 @@ interface ITelecomService { /** * @see TelecomServiceImpl#getDefaultDialerPackage */ - String getDefaultDialerPackage(); + String getDefaultDialerPackage(String callingPackage); /** * @see TelecomServiceImpl#getDefaultDialerPackage @@ -164,7 +164,7 @@ interface ITelecomService { /** * @see TelecomServiceImpl#getSystemDialerPackage */ - String getSystemDialerPackage(); + String getSystemDialerPackage(String callingPackage); /** * @see TelecomServiceImpl#dumpCallAnalytics @@ -262,12 +262,15 @@ interface ITelecomService { /** * @see TelecomServiceImpl#addNewIncomingCall */ - void addNewIncomingCall(in PhoneAccountHandle phoneAccount, in Bundle extras); + void addNewIncomingCall(in PhoneAccountHandle phoneAccount, in Bundle extras, + String callingPackage); /** * @see TelecomServiceImpl#addNewIncomingConference */ - void addNewIncomingConference(in PhoneAccountHandle phoneAccount, in Bundle extras); + void addNewIncomingConference(in PhoneAccountHandle phoneAccount, in Bundle extras, + String callingPackage); + /** * @see TelecomServiceImpl#addNewUnknownCall @@ -303,7 +306,7 @@ interface ITelecomService { /** * @see TelecomServiceImpl#createManageBlockedNumbersIntent **/ - Intent createManageBlockedNumbersIntent(); + Intent createManageBlockedNumbersIntent(String callingPackage); /** * @see TelecomServiceImpl#createLaunchEmergencyDialerIntent @@ -330,7 +333,8 @@ interface ITelecomService { /** * @see TelecomServiceImpl#acceptHandover */ - void acceptHandover(in Uri srcAddr, int videoState, in PhoneAccountHandle destAcct); + void acceptHandover(in Uri srcAddr, int videoState, in PhoneAccountHandle destAcct, + String callingPackage); /** * @see TelecomServiceImpl#setTestEmergencyPhoneAccountPackageNameFilter diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 71ffd6e2ec9f..869b170cf46a 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -7744,7 +7744,7 @@ public class TelephonyManager { * app has carrier privileges (see {@link #hasCarrierPrivileges}). * * TODO: remove this one. use {@link #rebootModem()} for reset type 1 and - * {@link #resetRadioConfig()} for reset type 3 + * {@link #resetRadioConfig()} for reset type 3 (b/116476729) * * @param resetType reset type: 1: reload NV reset, 2: erase NV reset, 3: factory NV reset * @return true on success; false on any failure. @@ -16188,7 +16188,8 @@ public class TelephonyManager { * may encounter an {@link IllegalStateException} when trying to register more callbacks. * * @param executor The executor of where the callback will execute. - * @param callback The {@link TelephonyCallback} object to register. + * @param callback The {@link TelephonyCallback} object to register. The caller should hold a + * reference to the callback. The framework only holds a weak reference. */ public void registerTelephonyCallback(@NonNull @CallbackExecutor Executor executor, @NonNull TelephonyCallback callback) { @@ -16283,7 +16284,8 @@ public class TelephonyManager { * @param includeLocationData Specifies if the caller would like to receive * location related information. * @param executor The executor of where the callback will execute. - * @param callback The {@link TelephonyCallback} object to register. + * @param callback The {@link TelephonyCallback} object to register. The caller should hold a + * reference to the callback. The framework only holds a weak reference. */ public void registerTelephonyCallback(@IncludeLocationData int includeLocationData, @NonNull @CallbackExecutor Executor executor, diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java index 5bae1ad72d93..f8048aa3731c 100644 --- a/telephony/java/android/telephony/ims/ImsMmTelManager.java +++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java @@ -539,7 +539,6 @@ public class ImsMmTelManager implements RegistrationManager { * <li>The caller has carrier privileges (see * {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on any * active subscription.</li> - * <li>The caller is the default SMS app for the device.</li> * </ul> * <p>The profile owner is an app that owns a managed profile on the device; for more details * see <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>. @@ -601,7 +600,6 @@ public class ImsMmTelManager implements RegistrationManager { * <li>The caller has carrier privileges (see * {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on any * active subscription.</li> - * <li>The caller is the default SMS app for the device.</li> * </ul> * <p>The profile owner is an app that owns a managed profile on the device; for more details * see <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>. @@ -649,7 +647,6 @@ public class ImsMmTelManager implements RegistrationManager { * <li>The caller has carrier privileges (see * {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on any * active subscription.</li> - * <li>The caller is the default SMS app for the device.</li> * </ul> * <p>The profile owner is an app that owns a managed profile on the device; for more details * see <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>. @@ -862,7 +859,6 @@ public class ImsMmTelManager implements RegistrationManager { * <li>The caller has carrier privileges (see * {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on any * active subscription.</li> - * <li>The caller is the default SMS app for the device.</li> * </ul> * <p>The profile owner is an app that owns a managed profile on the device; for more details * see <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>. @@ -937,7 +933,6 @@ public class ImsMmTelManager implements RegistrationManager { * <li>The caller has carrier privileges (see * {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on any * active subscription.</li> - * <li>The caller is the default SMS app for the device.</li> * </ul> * <p>The profile owner is an app that owns a managed profile on the device; for more details * see <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>. @@ -1111,7 +1106,6 @@ public class ImsMmTelManager implements RegistrationManager { * <li>The caller has carrier privileges (see * {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on any * active subscription.</li> - * <li>The caller is the default SMS app for the device.</li> * </ul> * <p>The profile owner is an app that owns a managed profile on the device; for more details * see <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>. @@ -1226,7 +1220,6 @@ public class ImsMmTelManager implements RegistrationManager { * <li>The caller has carrier privileges (see * {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on any * active subscription.</li> - * <li>The caller is the default SMS app for the device.</li> * </ul> * <p>The profile owner is an app that owns a managed profile on the device; for more details * see <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>. @@ -1415,7 +1408,6 @@ public class ImsMmTelManager implements RegistrationManager { * <li>The caller has carrier privileges (see * {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on any * active subscription.</li> - * <li>The caller is the default SMS app for the device.</li> * </ul> * <p>The profile owner is an app that owns a managed profile on the device; for more details * see <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>. diff --git a/telephony/java/android/telephony/ims/ImsRcsManager.java b/telephony/java/android/telephony/ims/ImsRcsManager.java index e00ea0ea4d5e..4439e5c35d83 100644 --- a/telephony/java/android/telephony/ims/ImsRcsManager.java +++ b/telephony/java/android/telephony/ims/ImsRcsManager.java @@ -540,6 +540,8 @@ public class ImsRcsManager { try { return imsRcsController.isCapable(mSubId, capability, radioTech); + } catch (ServiceSpecificException e) { + throw new ImsException(e.getMessage(), e.errorCode); } catch (RemoteException e) { Log.w(TAG, "Error calling IImsRcsController#isCapable", e); throw new ImsException("Remote IMS Service is not available", @@ -577,6 +579,8 @@ public class ImsRcsManager { try { return imsRcsController.isAvailable(mSubId, capability, radioTech); + } catch (ServiceSpecificException e) { + throw new ImsException(e.getMessage(), e.errorCode); } catch (RemoteException e) { Log.w(TAG, "Error calling IImsRcsController#isAvailable", e); throw new ImsException("Remote IMS Service is not available", diff --git a/telephony/java/android/telephony/ims/ImsService.java b/telephony/java/android/telephony/ims/ImsService.java index be233b82c426..50fcdf86be79 100644 --- a/telephony/java/android/telephony/ims/ImsService.java +++ b/telephony/java/android/telephony/ims/ImsService.java @@ -52,6 +52,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.HashMap; import java.util.Map; +import java.util.NoSuchElementException; import java.util.concurrent.CancellationException; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; @@ -188,6 +189,7 @@ public class ImsService extends Service { new SparseArray<>(); private IImsServiceControllerListener mListener; + private final Object mListenerLock = new Object(); private Executor mExecutor; /** @@ -225,7 +227,30 @@ public class ImsService extends Service { protected final IBinder mImsServiceController = new IImsServiceController.Stub() { @Override public void setListener(IImsServiceControllerListener l) { - mListener = l; + synchronized (mListenerLock) { + if (mListener != null && mListener.asBinder().isBinderAlive()) { + try { + mListener.asBinder().unlinkToDeath(mDeathRecipient, 0); + } catch (NoSuchElementException e) { + Log.w(LOG_TAG, "IImsServiceControllerListener does not exist"); + } + } + + mListener = l; + if (mListener == null) { + executeMethodAsync(() -> releaseResource(), "releaseResource"); + return; + } + + try { + mListener.asBinder().linkToDeath(mDeathRecipient, 0); + Log.i(LOG_TAG, "setListener: register linkToDeath"); + } catch (RemoteException e) { + // RemoteException means target binder process was crashed + // release resource + executeMethodAsync(() -> releaseResource(), "releaseResource"); + } + } } @Override @@ -364,28 +389,15 @@ public class ImsService extends Service { ImsService.this.disableImsForSubscription(slotId, subId), "disableIms"); } - // Call the methods with a clean calling identity on the executor and wait indefinitely for - // the future to return. - private void executeMethodAsync(Runnable r, String errorLogName) { - try { - CompletableFuture.runAsync( - () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join(); - } catch (CancellationException | CompletionException e) { - Log.w(LOG_TAG, "ImsService Binder - " + errorLogName + " exception: " - + e.getMessage()); - } - } - private <T> T executeMethodAsyncForResult(Supplier<T> r, String errorLogName) { - CompletableFuture<T> future = CompletableFuture.supplyAsync( - () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor); - try { - return future.get(); - } catch (ExecutionException | InterruptedException e) { - Log.w(LOG_TAG, "ImsService Binder - " + errorLogName + " exception: " - + e.getMessage()); - return null; - } + }; + + private final IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() { + @Override + public void binderDied() { + Log.w(LOG_TAG, + "IImsServiceControllerListener binder to framework has died. Cleaning up"); + executeMethodAsync(() -> releaseResource(), "releaseResource"); } }; @@ -490,6 +502,9 @@ public class ImsService extends Service { } private void removeImsFeature(int slotId, int featureType) { + // clear cached data + notifySubscriptionRemoved(slotId); + synchronized (mFeaturesBySlot) { // get ImsFeature associated with the slot/feature SparseArray<ImsFeature> features = mFeaturesBySlot.get(slotId); @@ -507,7 +522,6 @@ public class ImsService extends Service { f.onFeatureRemoved(); features.remove(featureType); } - } /** @@ -552,6 +566,54 @@ public class ImsService extends Service { return createFlag; } + private void releaseResource() { + Log.w(LOG_TAG, "cleaning up features"); + synchronized (mFeaturesBySlot) { + SparseArray<ImsFeature> features; + ImsFeature imsFeature; + + for (int i = 0; i < mFeaturesBySlot.size(); i++) { + features = mFeaturesBySlot.valueAt(i); + if (features == null) { + continue; + } + + for (int index = 0; index < features.size(); index++) { + imsFeature = features.valueAt(index); + if (imsFeature != null) { + imsFeature.onFeatureRemoved(); + } + } + features.clear(); + } + mFeaturesBySlot.clear(); + } + } + + // Call the methods with a clean calling identity on the executor and wait indefinitely for + // the future to return. + private void executeMethodAsync(Runnable r, String errorLogName) { + try { + CompletableFuture.runAsync( + () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join(); + } catch (CancellationException | CompletionException e) { + Log.w(LOG_TAG, "ImsService Binder - " + errorLogName + " exception: " + + e.getMessage()); + } + } + + private <T> T executeMethodAsyncForResult(Supplier<T> r, String errorLogName) { + CompletableFuture<T> future = CompletableFuture.supplyAsync( + () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor); + try { + return future.get(); + } catch (ExecutionException | InterruptedException e) { + Log.w(LOG_TAG, "ImsService Binder - " + errorLogName + " exception: " + + e.getMessage()); + return null; + } + } + /** * When called, provide the {@link ImsFeatureConfiguration} that this {@link ImsService} * currently supports. This will trigger the framework to set up the {@link ImsFeature}s that @@ -574,10 +636,14 @@ public class ImsService extends Service { */ public final void onUpdateSupportedImsFeatures(ImsFeatureConfiguration c) throws RemoteException { - if (mListener == null) { - throw new IllegalStateException("Framework is not ready"); + IImsServiceControllerListener l; + synchronized (mListenerLock) { + if (mListener == null) { + throw new IllegalStateException("Framework is not ready"); + } + l = mListener; } - mListener.onUpdateSupportedImsFeatures(c); + l.onUpdateSupportedImsFeatures(c); } /** @@ -629,6 +695,24 @@ public class ImsService extends Service { } /** + * The subscription has removed. The ImsService should notify ImsRegistrationImplBase and + * ImsConfigImplBase the SIM state was changed. + * @param slotId The slot ID which has removed. + */ + private void notifySubscriptionRemoved(int slotId) { + ImsRegistrationImplBase registrationImplBase = + getRegistration(slotId); + if (registrationImplBase != null) { + registrationImplBase.clearRegistrationCache(); + } + + ImsConfigImplBase imsConfigImplBase = getConfig(slotId); + if (imsConfigImplBase != null) { + imsConfigImplBase.clearConfigurationCache(); + } + } + + /** * The framework has enabled IMS for the slot specified, the ImsService should register for IMS * and perform all appropriate initialization to bring up all ImsFeatures. * @deprecated Use {@link #enableImsForSubscription} instead. diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java index 2833489d654c..f2976f14d7a6 100644 --- a/telephony/java/android/telephony/ims/ProvisioningManager.java +++ b/telephony/java/android/telephony/ims/ProvisioningManager.java @@ -54,6 +54,9 @@ import java.util.concurrent.Executor; * IMS provisioning keys are defined per carrier or OEM using OMA-DM or other provisioning * applications and may vary. It is up to the carrier and OEM applications to ensure that the * correct provisioning keys are being used when integrating with a vendor's ImsService. + * + * Use {@link android.telephony.ims.ImsManager#getProvisioningManager(int)} to get an instance of + * this manager. */ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_IMS) public class ProvisioningManager { diff --git a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java index f371ec3a28a7..897b57f48dad 100644 --- a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java @@ -481,6 +481,17 @@ public class ImsConfigImplBase { } } + /** + * Clear cached configuration value. + */ + public void clearCachedValue() { + Log.i(TAG, "clearCachedValue"); + synchronized (mLock) { + mProvisionedIntValue.clear(); + mProvisionedStringValue.clear(); + } + } + // Call the methods with a clean calling identity on the executor and wait indefinitely for // the future to return. private void executeMethodAsync(Runnable r, String errorLogName) throws RemoteException { @@ -538,6 +549,7 @@ public class ImsConfigImplBase { private final RemoteCallbackListExt<IRcsConfigCallback> mRcsCallbacks = new RemoteCallbackListExt<>(); private byte[] mRcsConfigData; + private final Object mRcsConfigDataLock = new Object(); ImsConfigStub mImsConfigStub; /** @@ -616,12 +628,20 @@ public class ImsConfigImplBase { private void addRcsConfigCallback(IRcsConfigCallback c) { mRcsCallbacks.register(c); - if (mRcsConfigData != null) { - try { - c.onConfigurationChanged(mRcsConfigData); - } catch (RemoteException e) { - Log.w(TAG, "dead binder to call onConfigurationChanged, skipping."); + + // This is used to avoid calling the binder out of the synchronized scope. + byte[] cloneRcsConfigData; + synchronized (mRcsConfigDataLock) { + if (mRcsConfigData == null) { + return; } + cloneRcsConfigData = mRcsConfigData.clone(); + } + + try { + c.onConfigurationChanged(cloneRcsConfigData); + } catch (RemoteException e) { + Log.w(TAG, "dead binder to call onConfigurationChanged, skipping."); } } @@ -631,18 +651,23 @@ public class ImsConfigImplBase { private void onNotifyRcsAutoConfigurationReceived(byte[] config, boolean isCompressed) { // cache uncompressed config - config = isCompressed ? RcsConfig.decompressGzip(config) : config; - if (Arrays.equals(mRcsConfigData, config)) { - return; + final byte[] rcsConfigData = isCompressed ? RcsConfig.decompressGzip(config) : config; + + synchronized (mRcsConfigDataLock) { + if (Arrays.equals(mRcsConfigData, config)) { + return; + } + mRcsConfigData = rcsConfigData; } - mRcsConfigData = config; // can be null in testing if (mRcsCallbacks != null) { synchronized (mRcsCallbacks) { mRcsCallbacks.broadcastAction(c -> { try { - c.onConfigurationChanged(mRcsConfigData); + // config is cloned here so modifications to the config passed to the + // vendor do not accidentally modify the cache. + c.onConfigurationChanged(rcsConfigData.clone()); } catch (RemoteException e) { Log.w(TAG, "dead binder in notifyRcsAutoConfigurationReceived, skipping."); } @@ -653,7 +678,9 @@ public class ImsConfigImplBase { } private void onNotifyRcsAutoConfigurationRemoved() { - mRcsConfigData = null; + synchronized (mRcsConfigDataLock) { + mRcsConfigData = null; + } if (mRcsCallbacks != null) { synchronized (mRcsCallbacks) { mRcsCallbacks.broadcastAction(c -> { @@ -857,4 +884,17 @@ public class ImsConfigImplBase { mImsConfigStub.mExecutor = executor; } } + + /** + * Clear all cached config data. This will be called when the config data is no longer valid + * such as when the SIM was removed. + * @hide + */ + public final void clearConfigurationCache() { + mImsConfigStub.clearCachedValue(); + + synchronized (mRcsConfigDataLock) { + mRcsConfigData = null; + } + } } diff --git a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java index 593f0807ef27..6fc1cc828a2c 100644 --- a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java @@ -517,4 +517,16 @@ public class ImsRegistrationImplBase { mExecutor = executor; } } + + /** + * Clear the cached data when the subscription is no longer valid + * such as when a sim is removed. + * @hide + */ + public final void clearRegistrationCache() { + synchronized (mLock) { + mUris = null; + mUrisSet = false; + } + } } diff --git a/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java b/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java index 7490d3f2b50c..ab83997c67fc 100644 --- a/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java +++ b/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java @@ -114,6 +114,63 @@ public class StagedInstallInternalTest { Uninstall.packages(TestApp.A, TestApp.B); } + private boolean isSystem(PackageInfo info) { + return (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; + } + + private boolean isUpdatedSystem(PackageInfo info) { + return (info.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0; + } + + @Test + public void testUpdateSystemApp_InstallV2() throws Exception { + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); + + PackageManager pm = + InstrumentationRegistry.getInstrumentation().getContext().getPackageManager(); + PackageInfo info; + // Check factory version + info = pm.getPackageInfo(TestApp.A, + PackageManager.PackageInfoFlags.of(PackageManager.MATCH_FACTORY_ONLY)); + assertThat(isSystem(info)).isTrue(); + assertThat(isUpdatedSystem(info)).isFalse(); + // Check active version + info = pm.getPackageInfo(TestApp.A, PackageManager.PackageInfoFlags.of(0)); + assertThat(isSystem(info)).isTrue(); + assertThat(isUpdatedSystem(info)).isFalse(); + + Install.single(TestApp.A2).commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); + + // Check factory version + info = pm.getPackageInfo(TestApp.A, + PackageManager.PackageInfoFlags.of(PackageManager.MATCH_FACTORY_ONLY)); + assertThat(isSystem(info)).isTrue(); + assertThat(isUpdatedSystem(info)).isFalse(); + // Check active version + info = pm.getPackageInfo(TestApp.A, PackageManager.PackageInfoFlags.of(0)); + assertThat(isSystem(info)).isTrue(); + assertThat(isUpdatedSystem(info)).isTrue(); + } + + @Test + public void testUpdateSystemApp_PostInstallV2() throws Exception { + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); + + PackageManager pm = + InstrumentationRegistry.getInstrumentation().getContext().getPackageManager(); + PackageInfo info; + // Check factory version + info = pm.getPackageInfo(TestApp.A, + PackageManager.PackageInfoFlags.of(PackageManager.MATCH_FACTORY_ONLY)); + assertThat(isSystem(info)).isTrue(); + assertThat(isUpdatedSystem(info)).isFalse(); + // Check active version + info = pm.getPackageInfo(TestApp.A, PackageManager.PackageInfoFlags.of(0)); + assertThat(isSystem(info)).isTrue(); + assertThat(isUpdatedSystem(info)).isTrue(); + } + @Test public void testDuplicateApkInApexShouldFail_Commit() throws Exception { assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); @@ -403,7 +460,8 @@ public class StagedInstallInternalTest { { PackageInfo apex = pm.getPackageInfo("test.apex.rebootless", PackageManager.MATCH_APEX); assertThat(apex.getLongVersionCode()).isEqualTo(1); - assertThat(apex.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM).isEqualTo(0); + assertThat(apex.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) + .isEqualTo(ApplicationInfo.FLAG_UPDATED_SYSTEM_APP); assertThat(apex.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) .isEqualTo(ApplicationInfo.FLAG_INSTALLED); assertThat(apex.applicationInfo.sourceDir).startsWith("/data/apex/active"); @@ -414,7 +472,8 @@ public class StagedInstallInternalTest { assertThat(apex.getLongVersionCode()).isEqualTo(1); assertThat(apex.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) .isEqualTo(ApplicationInfo.FLAG_SYSTEM); - assertThat(apex.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED).isEqualTo(0); + assertThat(apex.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) + .isEqualTo(ApplicationInfo.FLAG_INSTALLED); assertThat(apex.applicationInfo.sourceDir).startsWith("/system/apex"); } @@ -425,7 +484,8 @@ public class StagedInstallInternalTest { { PackageInfo apex = pm.getPackageInfo("test.apex.rebootless", PackageManager.MATCH_APEX); assertThat(apex.getLongVersionCode()).isEqualTo(2); - assertThat(apex.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM).isEqualTo(0); + assertThat(apex.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) + .isEqualTo(ApplicationInfo.FLAG_UPDATED_SYSTEM_APP); assertThat(apex.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) .isEqualTo(ApplicationInfo.FLAG_INSTALLED); assertThat(apex.applicationInfo.sourceDir).startsWith("/data/apex/active"); @@ -436,7 +496,8 @@ public class StagedInstallInternalTest { assertThat(apex.getLongVersionCode()).isEqualTo(1); assertThat(apex.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) .isEqualTo(ApplicationInfo.FLAG_SYSTEM); - assertThat(apex.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED).isEqualTo(0); + assertThat(apex.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) + .isEqualTo(ApplicationInfo.FLAG_INSTALLED); assertThat(apex.applicationInfo.sourceDir).startsWith("/system/apex"); } } diff --git a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java index f60b4d6aad1e..7e0a55ff3f3e 100644 --- a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java +++ b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java @@ -95,6 +95,7 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test { "/data/apex/active/" + SHIM_APEX_PACKAGE_NAME + "*.apex", "/system/apex/test.rebootless_apex_v*.apex", "/data/apex/active/test.apex.rebootless*.apex", + "/system/app/TestApp/TestAppAv1.apk", TEST_VENDOR_APEX_ALLOW_LIST); } @@ -163,6 +164,25 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test { } /** + * Tests app info flags are set correctly when updating a system app. + */ + @Test + public void testUpdateSystemApp() throws Exception { + // Push TestAppAv1.apk to /system + final File apkFile = mHostUtils.getTestFile(APK_A); + if (!getDevice().isAdbRoot()) { + getDevice().enableAdbRoot(); + } + getDevice().remountSystemWritable(); + assertTrue(getDevice().pushFile(apkFile, "/system/app/TestApp/" + apkFile.getName())); + getDevice().reboot(); + + runPhase("testUpdateSystemApp_InstallV2"); + getDevice().reboot(); + runPhase("testUpdateSystemApp_PostInstallV2"); + } + + /** * Tests that duplicate packages in apk-in-apex and apk should fail to install. */ @Test diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java index b7f5b15f72ac..f183a9b1d46c 100644 --- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java +++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java @@ -20,6 +20,7 @@ import android.content.Intent; import android.service.voice.AlwaysOnHotwordDetector; import android.service.voice.AlwaysOnHotwordDetector.Callback; import android.service.voice.AlwaysOnHotwordDetector.EventPayload; +import android.service.voice.HotwordDetector; import android.service.voice.VoiceInteractionService; import android.util.Log; @@ -83,16 +84,24 @@ public class MainInteractionService extends VoiceInteractionService { break; case AlwaysOnHotwordDetector.STATE_KEYPHRASE_UNENROLLED: Log.i(TAG, "STATE_KEYPHRASE_UNENROLLED"); - Intent enroll = mHotwordDetector.createEnrollIntent(); - Log.i(TAG, "Need to enroll with " + enroll); + try { + Intent enroll = mHotwordDetector.createEnrollIntent(); + Log.i(TAG, "Need to enroll with " + enroll); + } catch (HotwordDetector.IllegalDetectorStateException e) { + Log.e(TAG, "createEnrollIntent failed", e); + } break; case AlwaysOnHotwordDetector.STATE_KEYPHRASE_ENROLLED: Log.i(TAG, "STATE_KEYPHRASE_ENROLLED - starting recognition"); - if (mHotwordDetector.startRecognition( - AlwaysOnHotwordDetector.RECOGNITION_FLAG_NONE)) { - Log.i(TAG, "startRecognition succeeded"); - } else { - Log.i(TAG, "startRecognition failed"); + try { + if (mHotwordDetector.startRecognition( + AlwaysOnHotwordDetector.RECOGNITION_FLAG_NONE)) { + Log.i(TAG, "startRecognition succeeded"); + } else { + Log.i(TAG, "startRecognition failed"); + } + } catch (HotwordDetector.IllegalDetectorStateException e) { + Log.e(TAG, "startRecognition failed", e); } break; } diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp index bfb32854a374..0849600b0606 100644 --- a/tools/aapt2/Android.bp +++ b/tools/aapt2/Android.bp @@ -36,6 +36,7 @@ toolSources = [ cc_defaults { name: "aapt2_defaults", + cpp_std: "gnu++2b", cflags: [ "-Wall", "-Werror", diff --git a/tools/aapt2/Debug.cpp b/tools/aapt2/Debug.cpp index f47d66ea5e87..41896f622228 100644 --- a/tools/aapt2/Debug.cpp +++ b/tools/aapt2/Debug.cpp @@ -273,7 +273,7 @@ void Debug::PrintTable(const ResourceTable& table, const DebugPrintTableOptions& printer->Indent(); for (const auto& type : package.types) { printer->Print("type "); - printer->Print(to_string(type.type)); + printer->Print(type.named_type.to_string()); if (type.id) { printer->Print(StringPrintf(" id=%02x", type.id.value())); } @@ -287,7 +287,7 @@ void Debug::PrintTable(const ResourceTable& table, const DebugPrintTableOptions& printer->Print(" "); // Write the name without the package (this is obvious and too verbose). - printer->Print(to_string(type.type)); + printer->Print(type.named_type.to_string()); printer->Print("/"); printer->Print(entry.name); @@ -547,7 +547,7 @@ void Debug::DumpOverlayable(const ResourceTable& table, text::Printer* printer) const auto policy_subsection = StringPrintf(R"(policies="%s")", android::idmap2::policy::PoliciesToDebugString(overlayable_item.policies).c_str()); const auto value = - StringPrintf("%s/%s", to_string(type->type).data(), entry->name.c_str()); + StringPrintf("%s/%s", type->named_type.to_string().data(), entry->name.c_str()); items.push_back(DumpOverlayableEntry{overlayable_section, policy_subsection, value}); } } diff --git a/tools/aapt2/Resource.cpp b/tools/aapt2/Resource.cpp index 0bb330e26e6f..df8c3b9956d0 100644 --- a/tools/aapt2/Resource.cpp +++ b/tools/aapt2/Resource.cpp @@ -139,10 +139,10 @@ ResourceNamedTypeRef ResourceNamedTypeWithDefaultName(ResourceType t) { } std::optional<ResourceNamedTypeRef> ParseResourceNamedType(const android::StringPiece& s) { - auto colon = std::find(s.begin(), s.end(), ':'); + auto dot = std::find(s.begin(), s.end(), '.'); const ResourceType* parsedType; - if (colon != s.end() && colon != std::prev(s.end())) { - parsedType = ParseResourceType(s.substr(s.begin(), colon)); + if (dot != s.end() && dot != std::prev(s.end())) { + parsedType = ParseResourceType(s.substr(s.begin(), dot)); } else { parsedType = ParseResourceType(s); } diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp index 8d35eeec2a93..a99e4b234c6b 100644 --- a/tools/aapt2/ResourceParser.cpp +++ b/tools/aapt2/ResourceParser.cpp @@ -981,12 +981,14 @@ bool static ParseGroupImpl(xml::XmlPullParser* parser, ParsedResource* out_resou return false; } - std::optional<ResourceNamedTypeRef> parsed_type = ParseResourceNamedType(maybe_type.value()); - if (!parsed_type) { + std::optional<ResourceNamedTypeRef> maybe_parsed_type = + ParseResourceNamedType(maybe_type.value()); + if (!maybe_parsed_type) { diag->Error(DiagMessage(out_resource->source) << "invalid resource type '" << maybe_type.value() << "' in <" << tag_name << ">"); return false; } + auto parsed_type = maybe_parsed_type->ToResourceNamedType(); std::optional<StringPiece> maybe_id_str = xml::FindNonEmptyAttribute(parser, "first-id"); if (!maybe_id_str) { @@ -1046,7 +1048,7 @@ bool static ParseGroupImpl(xml::XmlPullParser* parser, ParsedResource* out_resou } ParsedResource& entry_res = out_resource->child_resources.emplace_back(ParsedResource{ - .name = ResourceName{{}, *parsed_type, maybe_name.value().to_string()}, + .name = ResourceName{{}, parsed_type, maybe_name.value().to_string()}, .source = item_source, .comment = std::move(comment), }); diff --git a/tools/aapt2/ResourceTable.cpp b/tools/aapt2/ResourceTable.cpp index 98cce268e213..0f5118da9408 100644 --- a/tools/aapt2/ResourceTable.cpp +++ b/tools/aapt2/ResourceTable.cpp @@ -43,8 +43,9 @@ namespace aapt { const char* Overlayable::kActorScheme = "overlay"; namespace { -bool less_than_type(const std::unique_ptr<ResourceTableType>& lhs, ResourceType rhs) { - return lhs->type < rhs; +bool less_than_type(const std::unique_ptr<ResourceTableType>& lhs, + const ResourceNamedTypeRef& rhs) { + return lhs->named_type < rhs; } template <typename T> @@ -115,18 +116,24 @@ ResourceTablePackage* ResourceTable::FindOrCreatePackage(const android::StringPi } template <typename Func, typename Elements> -static ResourceTableType* FindTypeRunAction(ResourceType type, Elements& entries, Func action) { +static ResourceTableType* FindTypeRunAction(const ResourceNamedTypeRef& type, Elements& entries, + Func action) { const auto iter = std::lower_bound(entries.begin(), entries.end(), type, less_than_type); - const bool found = iter != entries.end() && type == (*iter)->type; + const bool found = iter != entries.end() && type == (*iter)->named_type; return action(found, iter); } -ResourceTableType* ResourceTablePackage::FindType(ResourceType type) const { +ResourceTableType* ResourceTablePackage::FindTypeWithDefaultName(const ResourceType type) const { + auto named_type = ResourceNamedTypeWithDefaultName(type); + return FindType(named_type); +} + +ResourceTableType* ResourceTablePackage::FindType(const ResourceNamedTypeRef& type) const { return FindTypeRunAction(type, types, [&](bool found, auto& iter) { return found ? iter->get() : nullptr; }); } -ResourceTableType* ResourceTablePackage::FindOrCreateType(ResourceType type) { +ResourceTableType* ResourceTablePackage::FindOrCreateType(const ResourceNamedTypeRef& type) { return FindTypeRunAction(type, types, [&](bool found, auto& iter) { return found ? iter->get() : types.emplace(iter, new ResourceTableType(type))->get(); }); @@ -329,7 +336,7 @@ struct PackageViewComparer { struct TypeViewComparer { bool operator()(const ResourceTableTypeView& lhs, const ResourceTableTypeView& rhs) { - return lhs.id != rhs.id ? lhs.id < rhs.id : lhs.type < rhs.type; + return lhs.id != rhs.id ? lhs.id < rhs.id : lhs.named_type < rhs.named_type; } }; @@ -355,7 +362,8 @@ void InsertEntryIntoTableView(ResourceTableView& table, const ResourceTablePacka id ? id.value().package_id() : std::optional<uint8_t>{}}; auto view_package = package_inserter.Insert(table.packages, std::move(new_package)); - ResourceTableTypeView new_type{type->type, id ? id.value().type_id() : std::optional<uint8_t>{}}; + ResourceTableTypeView new_type{type->named_type, + id ? id.value().type_id() : std::optional<uint8_t>{}}; auto view_type = type_inserter.Insert(view_package->types, std::move(new_type)); if (visibility.level == Visibility::Level::kPublic) { @@ -420,13 +428,14 @@ ResourceTableView ResourceTable::GetPartitionedView(const ResourceTableViewOptio // we can reuse those packages for other types that need to be extracted from this package. // `start_index` is the index of the first newly created package that can be reused. const size_t start_index = new_packages.size(); - std::map<ResourceType, size_t> type_new_package_index; + std::map<ResourceNamedType, size_t> type_new_package_index; for (auto type_it = package.types.begin(); type_it != package.types.end();) { auto& type = *type_it; - auto type_index_iter = type_new_package_index.find(type.type); + auto type_index_iter = type_new_package_index.find(type.named_type); if (type_index_iter == type_new_package_index.end()) { // First occurrence of the resource type in this package. Keep it in this package. - type_new_package_index.insert(type_index_iter, std::make_pair(type.type, start_index)); + type_new_package_index.insert(type_index_iter, + std::make_pair(type.named_type, start_index)); ++type_it; continue; } @@ -440,7 +449,7 @@ ResourceTableView ResourceTable::GetPartitionedView(const ResourceTableViewOptio // Move the type into a new package auto& other_package = new_packages[index]; - type_new_package_index[type.type] = index + 1; + type_new_package_index[type.named_type] = index + 1; type_inserter.Insert(other_package.types, std::move(type)); type_it = package.types.erase(type_it); } @@ -473,7 +482,7 @@ bool ResourceTable::AddResource(NewResource&& res, IDiagnostics* diag) { } auto package = FindOrCreatePackage(res.name.package); - auto type = package->FindOrCreateType(res.name.type.type); + auto type = package->FindOrCreateType(res.name.type); auto entry_it = std::equal_range(type->entries.begin(), type->entries.end(), res.name.entry, NameEqualRange<ResourceEntry>{}); const size_t entry_count = std::distance(entry_it.first, entry_it.second); @@ -593,7 +602,7 @@ std::optional<ResourceTable::SearchResult> ResourceTable::FindResource( return {}; } - ResourceTableType* type = package->FindType(name.type.type); + ResourceTableType* type = package->FindType(name.type); if (type == nullptr) { return {}; } @@ -612,7 +621,7 @@ std::optional<ResourceTable::SearchResult> ResourceTable::FindResource(const Res return {}; } - ResourceTableType* type = package->FindType(name.type.type); + ResourceTableType* type = package->FindType(name.type); if (type == nullptr) { return {}; } @@ -633,7 +642,7 @@ bool ResourceTable::RemoveResource(const ResourceNameRef& name, ResourceId id) c return {}; } - ResourceTableType* type = package->FindType(name.type.type); + ResourceTableType* type = package->FindType(name.type); if (type == nullptr) { return {}; } @@ -655,7 +664,7 @@ std::unique_ptr<ResourceTable> ResourceTable::Clone() const { for (const auto& pkg : packages) { ResourceTablePackage* new_pkg = new_table->FindOrCreatePackage(pkg->name); for (const auto& type : pkg->types) { - ResourceTableType* new_type = new_pkg->FindOrCreateType(type->type); + ResourceTableType* new_type = new_pkg->FindOrCreateType(type->named_type); new_type->visibility_level = type->visibility_level; for (const auto& entry : type->entries) { diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h index 2e17659b0679..7aa8b0f0c8ef 100644 --- a/tools/aapt2/ResourceTable.h +++ b/tools/aapt2/ResourceTable.h @@ -168,7 +168,7 @@ class ResourceEntry { class ResourceTableType { public: // The logical type of resource (string, drawable, layout, etc.). - const ResourceType type; + const ResourceNamedType named_type; // Whether this type is public (and must maintain the same type ID across builds). Visibility::Level visibility_level = Visibility::Level::kUndefined; @@ -176,7 +176,9 @@ class ResourceTableType { // List of resources for this type. std::vector<std::unique_ptr<ResourceEntry>> entries; - explicit ResourceTableType(const ResourceType type) : type(type) {} + explicit ResourceTableType(const ResourceNamedTypeRef& type) + : named_type(type.ToResourceNamedType()) { + } ResourceEntry* CreateEntry(const android::StringPiece& name); ResourceEntry* FindEntry(const android::StringPiece& name) const; @@ -196,8 +198,9 @@ class ResourceTablePackage { } ResourceTablePackage() = default; - ResourceTableType* FindType(ResourceType type) const; - ResourceTableType* FindOrCreateType(ResourceType type); + ResourceTableType* FindTypeWithDefaultName(const ResourceType type) const; + ResourceTableType* FindType(const ResourceNamedTypeRef& type) const; + ResourceTableType* FindOrCreateType(const ResourceNamedTypeRef& type); private: DISALLOW_COPY_AND_ASSIGN(ResourceTablePackage); @@ -217,7 +220,7 @@ struct ResourceTableEntryView { }; struct ResourceTableTypeView { - ResourceType type; + ResourceNamedType named_type; std::optional<uint8_t> id; Visibility::Level visibility_level = Visibility::Level::kUndefined; diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp index 23f6c88aad91..b4e79ca8ca08 100644 --- a/tools/aapt2/ResourceUtils.cpp +++ b/tools/aapt2/ResourceUtils.cpp @@ -40,6 +40,23 @@ using ::android::base::StringPrintf; namespace aapt { namespace ResourceUtils { +static std::optional<ResourceNamedType> ToResourceNamedType(const char16_t* type16, + const char* type, size_t type_len) { + std::optional<ResourceNamedTypeRef> parsed_type; + if (type16) { + auto converted = util::Utf16ToUtf8(StringPiece16(type16, type_len)); + parsed_type = ParseResourceNamedType(converted); + } else if (type) { + parsed_type = ParseResourceNamedType(StringPiece(type, type_len)); + } else { + return {}; + } + if (!parsed_type) { + return {}; + } + return parsed_type->ToResourceNamedType(); +} + std::optional<ResourceName> ToResourceName(const android::ResTable::resource_name& name_in) { // TODO: Remove this when ResTable and AssetManager(1) are removed from AAPT2 ResourceName name_out; @@ -50,20 +67,12 @@ std::optional<ResourceName> ToResourceName(const android::ResTable::resource_nam name_out.package = util::Utf16ToUtf8(StringPiece16(name_in.package, name_in.packageLen)); - std::optional<ResourceNamedTypeRef> type; - if (name_in.type) { - type = ParseResourceNamedType(util::Utf16ToUtf8(StringPiece16(name_in.type, name_in.typeLen))); - } else if (name_in.type8) { - type = ParseResourceNamedType(StringPiece(name_in.type8, name_in.typeLen)); - } else { - return {}; - } - + std::optional<ResourceNamedType> type = + ToResourceNamedType(name_in.type, name_in.name8, name_in.typeLen); if (!type) { return {}; } - - name_out.type = type->ToResourceNamedType(); + name_out.type = *type; if (name_in.name) { name_out.entry = @@ -84,21 +93,12 @@ std::optional<ResourceName> ToResourceName(const android::AssetManager2::Resourc name_out.package = std::string(name_in.package, name_in.package_len); - std::optional<ResourceNamedTypeRef> type; - if (name_in.type16) { - type = - ParseResourceNamedType(util::Utf16ToUtf8(StringPiece16(name_in.type16, name_in.type_len))); - } else if (name_in.type) { - type = ParseResourceNamedType(StringPiece(name_in.type, name_in.type_len)); - } else { - return {}; - } - + std::optional<ResourceNamedType> type = + ToResourceNamedType(name_in.type16, name_in.type, name_in.type_len); if (!type) { return {}; } - - name_out.type = type->ToResourceNamedType(); + name_out.type = *type; if (name_in.entry16) { name_out.entry = diff --git a/tools/aapt2/Resource_test.cpp b/tools/aapt2/Resource_test.cpp index 2c55d1d548db..01d3c84e05ba 100644 --- a/tools/aapt2/Resource_test.cpp +++ b/tools/aapt2/Resource_test.cpp @@ -135,13 +135,13 @@ TEST(ResourceTypeTest, ParseResourceNamedType) { type = ParseResourceNamedType("layout"); EXPECT_THAT(type, Optional(Eq(ResourceNamedType("layout", ResourceType::kLayout)))); - type = ParseResourceNamedType("layout:2"); - EXPECT_THAT(type, Optional(Eq(ResourceNamedType("layout:2", ResourceType::kLayout)))); + type = ParseResourceNamedType("layout.2"); + EXPECT_THAT(type, Optional(Eq(ResourceNamedType("layout.2", ResourceType::kLayout)))); - type = ParseResourceNamedType("layout:another"); - EXPECT_THAT(type, Optional(Eq(ResourceNamedType("layout:another", ResourceType::kLayout)))); + type = ParseResourceNamedType("layout.another"); + EXPECT_THAT(type, Optional(Eq(ResourceNamedType("layout.another", ResourceType::kLayout)))); - type = ParseResourceNamedType("layout:"); + type = ParseResourceNamedType("layout."); EXPECT_THAT(type, Eq(std::nullopt)); type = ParseResourceNamedType("layout2"); diff --git a/tools/aapt2/SdkConstants.cpp b/tools/aapt2/SdkConstants.cpp index 8ea43abff895..34e8edb0a47f 100644 --- a/tools/aapt2/SdkConstants.cpp +++ b/tools/aapt2/SdkConstants.cpp @@ -27,7 +27,7 @@ namespace aapt { static ApiVersion sDevelopmentSdkLevel = 10000; static const auto sDevelopmentSdkCodeNames = - std::unordered_set<StringPiece>({"Q", "R", "S", "Sv2", "Tiramisu"}); + std::unordered_set<StringPiece>({"Q", "R", "S", "Sv2", "Tiramisu", "UpsideDownCake"}); static const std::vector<std::pair<uint16_t, ApiVersion>> sAttrIdMap = { {0x021c, 1}, diff --git a/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp index fe560180bd48..e27b9aae26fa 100644 --- a/tools/aapt2/cmd/Compile.cpp +++ b/tools/aapt2/cmd/Compile.cpp @@ -243,9 +243,9 @@ static bool CompileTable(IAaptContext* context, const CompileOptions& options, r_txt_printer.Print("private "); } - if (type->type != ResourceType::kStyleable) { + if (type->named_type.type != ResourceType::kStyleable) { r_txt_printer.Print("int "); - r_txt_printer.Print(to_string(type->type)); + r_txt_printer.Print(type->named_type.to_string()); r_txt_printer.Print(" "); r_txt_printer.Println(entry->name); } else { diff --git a/tools/aapt2/cmd/Diff.cpp b/tools/aapt2/cmd/Diff.cpp index d9e8c921dbc5..a854146c28f6 100644 --- a/tools/aapt2/cmd/Diff.cpp +++ b/tools/aapt2/cmd/Diff.cpp @@ -105,7 +105,7 @@ static bool EmitResourceConfigValueDiff( Value* value_b = config_value_b->value.get(); if (!value_a->Equals(value_b)) { std::stringstream str_stream; - str_stream << "value " << pkg_a.name << ":" << type_a.type << "/" << entry_a.name + str_stream << "value " << pkg_a.name << ":" << type_a.named_type << "/" << entry_a.name << " config=" << config_value_a->config << " does not match:\n"; value_a->Print(&str_stream); str_stream << "\n vs \n"; @@ -128,7 +128,7 @@ static bool EmitResourceEntryDiff(IAaptContext* context, LoadedApk* apk_a, auto config_value_b = entry_b.FindValue(config_value_a->config); if (!config_value_b) { std::stringstream str_stream; - str_stream << "missing " << pkg_a.name << ":" << type_a.type << "/" << entry_a.name + str_stream << "missing " << pkg_a.name << ":" << type_a.named_type << "/" << entry_a.name << " config=" << config_value_a->config; EmitDiffLine(apk_b->GetSource(), str_stream.str()); diff = true; @@ -143,7 +143,7 @@ static bool EmitResourceEntryDiff(IAaptContext* context, LoadedApk* apk_a, auto config_value_a = entry_a.FindValue(config_value_b->config); if (!config_value_a) { std::stringstream str_stream; - str_stream << "new config " << pkg_b.name << ":" << type_b.type << "/" << entry_b.name + str_stream << "new config " << pkg_b.name << ":" << type_b.named_type << "/" << entry_b.name << " config=" << config_value_b->config; EmitDiffLine(apk_b->GetSource(), str_stream.str()); diff = true; @@ -164,13 +164,15 @@ static bool EmitResourceTypeDiff(IAaptContext* context, LoadedApk* apk_a, if (entry_b_iter == type_b.entries.end()) { // Type A contains a type that type B does not have. std::stringstream str_stream; - str_stream << "missing " << pkg_a.name << ":" << type_a.type << "/" << entry_a_iter->name; + str_stream << "missing " << pkg_a.name << ":" << type_a.named_type << "/" + << entry_a_iter->name; EmitDiffLine(apk_a->GetSource(), str_stream.str()); diff = true; } else if (entry_a_iter == type_a.entries.end()) { // Type B contains a type that type A does not have. std::stringstream str_stream; - str_stream << "new entry " << pkg_b.name << ":" << type_b.type << "/" << entry_b_iter->name; + str_stream << "new entry " << pkg_b.name << ":" << type_b.named_type << "/" + << entry_b_iter->name; EmitDiffLine(apk_b->GetSource(), str_stream.str()); diff = true; } else { @@ -178,7 +180,7 @@ static bool EmitResourceTypeDiff(IAaptContext* context, LoadedApk* apk_a, const auto& entry_b = *entry_b_iter; if (IsSymbolVisibilityDifferent(entry_a.visibility, entry_b.visibility)) { std::stringstream str_stream; - str_stream << pkg_a.name << ":" << type_a.type << "/" << entry_a.name + str_stream << pkg_a.name << ":" << type_a.named_type << "/" << entry_a.name << " has different visibility ("; if (entry_b.visibility.staged_api) { str_stream << "STAGED "; @@ -203,7 +205,7 @@ static bool EmitResourceTypeDiff(IAaptContext* context, LoadedApk* apk_a, } else if (IsIdDiff(entry_a.visibility.level, entry_a.id, entry_b.visibility.level, entry_b.id)) { std::stringstream str_stream; - str_stream << pkg_a.name << ":" << type_a.type << "/" << entry_a.name + str_stream << pkg_a.name << ":" << type_a.named_type << "/" << entry_a.name << " has different public ID ("; if (entry_b.id) { str_stream << "0x" << std::hex << entry_b.id.value(); @@ -243,13 +245,13 @@ static bool EmitResourcePackageDiff(IAaptContext* context, LoadedApk* apk_a, if (type_b_iter == pkg_b.types.end()) { // Type A contains a type that type B does not have. std::stringstream str_stream; - str_stream << "missing " << pkg_a.name << ":" << type_a_iter->type; + str_stream << "missing " << pkg_a.name << ":" << type_a_iter->named_type; EmitDiffLine(apk_a->GetSource(), str_stream.str()); diff = true; } else if (type_a_iter == pkg_a.types.end()) { // Type B contains a type that type A does not have. std::stringstream str_stream; - str_stream << "new type " << pkg_b.name << ":" << type_b_iter->type; + str_stream << "new type " << pkg_b.name << ":" << type_b_iter->named_type; EmitDiffLine(apk_b->GetSource(), str_stream.str()); diff = true; } else { @@ -257,7 +259,7 @@ static bool EmitResourcePackageDiff(IAaptContext* context, LoadedApk* apk_a, const auto& type_b = *type_b_iter; if (type_a.visibility_level != type_b.visibility_level) { std::stringstream str_stream; - str_stream << pkg_a.name << ":" << type_a.type << " has different visibility ("; + str_stream << pkg_a.name << ":" << type_a.named_type << " has different visibility ("; if (type_b.visibility_level == Visibility::Level::kPublic) { str_stream << "PUBLIC"; } else { @@ -274,7 +276,7 @@ static bool EmitResourcePackageDiff(IAaptContext* context, LoadedApk* apk_a, diff = true; } else if (IsIdDiff(type_a.visibility_level, type_a.id, type_b.visibility_level, type_b.id)) { std::stringstream str_stream; - str_stream << pkg_a.name << ":" << type_a.type << " has different public ID ("; + str_stream << pkg_a.name << ":" << type_a.named_type << " has different public ID ("; if (type_b.id) { str_stream << "0x" << std::hex << type_b.id.value(); } else { diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp index 790f2b34c58b..bd74cc7be350 100644 --- a/tools/aapt2/cmd/Link.cpp +++ b/tools/aapt2/cmd/Link.cpp @@ -556,7 +556,7 @@ bool ResourceFileFlattener::Flatten(ResourceTable* table, IArchiveWriter* archiv file_op.config = config_value->config; file_op.file_to_copy = file; - if (type->type != ResourceType::kRaw && + if (type->named_type.type != ResourceType::kRaw && (file_ref->type == ResourceFile::Type::kBinaryXml || file_ref->type == ResourceFile::Type::kProtoXml)) { std::unique_ptr<io::IData> data = file->OpenAsData(); @@ -596,7 +596,8 @@ bool ResourceFileFlattener::Flatten(ResourceTable* table, IArchiveWriter* archiv file_op.xml_to_flatten->file.config = config_value->config; file_op.xml_to_flatten->file.source = file_ref->GetSource(); - file_op.xml_to_flatten->file.name = ResourceName(pkg->name, type->type, entry->name); + file_op.xml_to_flatten->file.name = + ResourceName(pkg->name, type->named_type, entry->name); } // NOTE(adamlesinski): Explicitly construct a StringPiece here, or @@ -1009,7 +1010,7 @@ class Linker { // We have a package that is not related to the one we're building! for (const auto& type : package->types) { for (const auto& entry : type->entries) { - ResourceNameRef res_name(package->name, type->type, entry->name); + ResourceNameRef res_name(package->name, type->named_type, entry->name); for (const auto& config_value : entry->values) { // Special case the occurrence of an ID that is being generated @@ -1046,7 +1047,7 @@ class Linker { for (const auto& type : package->types) { for (const auto& entry : type->entries) { if (entry->id) { - ResourceNameRef res_name(package->name, type->type, entry->name); + ResourceNameRef res_name(package->name, type->named_type, entry->name); context_->GetDiagnostics()->Error(DiagMessage() << "resource " << res_name << " has ID " << entry->id.value() << " assigned"); return false; @@ -1057,6 +1058,83 @@ class Linker { return true; } + bool VerifyLocaleFormat(xml::XmlResource* manifest, IDiagnostics* diag) { + // Skip it if the Manifest doesn't declare the localeConfig attribute within the <application> + // element. + const xml::Element* application = manifest->root->FindChild("", "application"); + if (!application) { + return true; + } + const xml::Attribute* localeConfig = + application->FindAttribute(xml::kSchemaAndroid, "localeConfig"); + if (!localeConfig) { + return true; + } + + if (localeConfig->compiled_value) { + const auto localeconfig_reference = ValueCast<Reference>(localeConfig->compiled_value.get()); + const auto localeconfig_entry = + ResolveTableEntry(context_, &final_table_, localeconfig_reference); + if (!localeconfig_entry) { + return true; + } + + for (const auto& value : localeconfig_entry->values) { + // Load an XML file which is linked from the localeConfig attribute. + const std::string& path = value->value->GetSource().path; + std::unique_ptr<xml::XmlResource> localeConfig_xml = LoadXml(path, diag); + if (!localeConfig_xml) { + diag->Error(DiagMessage(path) << "can't load the XML"); + return false; + } + + xml::Element* localeConfig_el = xml::FindRootElement(localeConfig_xml->root.get()); + if (!localeConfig_el) { + diag->Error(DiagMessage(path) << "no root tag defined"); + return false; + } + if (localeConfig_el->name != "locale-config") { + diag->Error(DiagMessage(path) << "invalid element name: " << localeConfig_el->name + << ", expected: locale-config"); + return false; + } + + for (const xml::Element* child_el : localeConfig_el->GetChildElements()) { + if (child_el->name == "locale") { + if (const xml::Attribute* locale_name_attr = + child_el->FindAttribute(xml::kSchemaAndroid, "name")) { + const std::string& locale_name = locale_name_attr->value; + const std::string valid_name = ConvertToBCP47Tag(locale_name); + + // Start to verify the locale format + ConfigDescription config; + if (!ConfigDescription::Parse(valid_name, &config)) { + diag->Error(DiagMessage(path) << "invalid configuration: " << locale_name); + return false; + } + } else { + diag->Error(DiagMessage(path) << "the attribute android:name is not found"); + return false; + } + } else { + diag->Error(DiagMessage(path) + << "invalid element name: " << child_el->name << ", expected: locale"); + return false; + } + } + } + } + return true; + } + + std::string ConvertToBCP47Tag(const std::string& locale) { + std::string bcp47tag = "b+"; + bcp47tag += locale; + std::replace(bcp47tag.begin(), bcp47tag.end(), '-', '+'); + + return bcp47tag; + } + std::unique_ptr<IArchiveWriter> MakeArchiveWriter(const StringPiece& out) { if (options_.output_to_directory) { return CreateDirectoryArchiveWriter(context_->GetDiagnostics(), out); @@ -1939,7 +2017,7 @@ class Linker { for (auto& package : final_table_.packages) { for (auto& type : package->types) { for (auto& entry : type->entries) { - ResourceName name(package->name, type->type, entry->name); + ResourceName name(package->name, type->named_type, entry->name); // The IDs are guaranteed to exist. options_.stable_id_map[std::move(name)] = entry->id.value(); } @@ -2180,6 +2258,10 @@ class Linker { return 1; } + if (!VerifyLocaleFormat(manifest_xml.get(), context_->GetDiagnostics())) { + return 1; + }; + if (!WriteApk(archive_writer.get(), &proguard_keep_set, manifest_xml.get(), &final_table_)) { return 1; } diff --git a/tools/aapt2/cmd/Link_test.cpp b/tools/aapt2/cmd/Link_test.cpp index 430c184ef87d..7b1236ab4a5e 100644 --- a/tools/aapt2/cmd/Link_test.cpp +++ b/tools/aapt2/cmd/Link_test.cpp @@ -22,6 +22,7 @@ #include "LoadedApk.h" #include "test/Test.h" +using android::ConfigDescription; using testing::Eq; using testing::HasSubstr; using testing::IsNull; @@ -783,4 +784,51 @@ TEST_F(LinkTest, MacroSubstitution) { EXPECT_THAT(xml_attrs[1].value, Eq("Hello World!")); } +TEST_F(LinkTest, ParseLocaleConfig) { + StdErrDiagnostics diag; + const std::string xml_values = + R"(<locale-config xmlns:android="http://schemas.android.com/apk/res/android"> + <locale android:name="pt"/> + <locale android:name="chr"/> + <locale android:name="chr-US"/> + <locale android:name="zh-Hant"/> + <locale android:name="es-419"/> + <locale android:name="en-US"/> + <locale android:name="zh-Hans-SG"/> + </locale-config>)"; + + const std::string res = GetTestPath("test-res"); + ASSERT_TRUE(CompileFile(GetTestPath("res/xml/locale_config.xml"), xml_values, res, &diag)); + + const std::string out_apk = GetTestPath("out.apk"); + auto link_args = LinkCommandBuilder(this) + .SetManifestFile(ManifestBuilder(this).SetPackageName("com.test").Build()) + .AddCompiledResDir(res, &diag) + .AddFlag("--no-auto-version") + .Build(out_apk); + ASSERT_TRUE(Link(link_args, &diag)); + + std::unique_ptr<LoadedApk> apk = LoadedApk::LoadApkFromPath(out_apk, &diag); + ASSERT_THAT(apk, Ne(nullptr)); + + auto xml = apk->LoadXml("res/xml/locale_config.xml", &diag); + ASSERT_THAT(xml, NotNull()); + EXPECT_THAT(xml->root->name, Eq("locale-config")); + ASSERT_THAT(xml->root->children.size(), Eq(7)); + for (auto& node : xml->root->children) { + const xml::Element* child_el = xml::NodeCast<xml::Element>(node.get()); + ASSERT_THAT(child_el, NotNull()); + EXPECT_THAT(child_el->name, Eq("locale")); + + auto& xml_attrs = child_el->attributes; + for (auto& attr : xml_attrs) { + std::string locale = "b+"; + locale += attr.value; + std::replace(locale.begin(), locale.end(), '-', '+'); + ConfigDescription config; + ASSERT_TRUE(ConfigDescription::Parse(locale, &config)); + } + } +} + } // namespace aapt diff --git a/tools/aapt2/cmd/Optimize.cpp b/tools/aapt2/cmd/Optimize.cpp index caa3e60d6af1..e1370fd10ef3 100644 --- a/tools/aapt2/cmd/Optimize.cpp +++ b/tools/aapt2/cmd/Optimize.cpp @@ -254,7 +254,7 @@ class Optimizer { } if (file_ref->file == nullptr) { - ResourceNameRef name(pkg->name, type->type, entry->name); + ResourceNameRef name(pkg->name, type->named_type, entry->name); context_->GetDiagnostics()->Warn(DiagMessage(file_ref->GetSource()) << "file for resource " << name << " with config '" << config_value->config << "' not found"); diff --git a/tools/aapt2/compile/IdAssigner.cpp b/tools/aapt2/compile/IdAssigner.cpp index fa816be43be3..29f9a08f9a10 100644 --- a/tools/aapt2/compile/IdAssigner.cpp +++ b/tools/aapt2/compile/IdAssigner.cpp @@ -128,7 +128,7 @@ bool IdAssigner::Consume(IAaptContext* context, ResourceTable* table) { for (auto& package : table->packages) { for (auto& type : package->types) { for (auto& entry : type->entries) { - const ResourceName name(package->name, type->type, entry->name); + const ResourceName name(package->name, type->named_type, entry->name); if (entry->id && !assigned_ids.ReserveId(name, entry->id.value(), entry->visibility, context->GetDiagnostics())) { return false; @@ -175,7 +175,7 @@ bool IdAssigner::Consume(IAaptContext* context, ResourceTable* table) { for (auto& package : table->packages) { for (auto& type : package->types) { for (auto& entry : type->entries) { - const ResourceName name(package->name, type->type, entry->name); + const ResourceName name(package->name, type->named_type, entry->name); if (entry->id) { continue; } diff --git a/tools/aapt2/compile/IdAssigner_test.cpp b/tools/aapt2/compile/IdAssigner_test.cpp index d3575716ae4f..8911dad39470 100644 --- a/tools/aapt2/compile/IdAssigner_test.cpp +++ b/tools/aapt2/compile/IdAssigner_test.cpp @@ -191,12 +191,12 @@ TEST_F(IdAssignerTests, ExaustEntryIdsLastIdIsPublic) { for (auto& entry : type->entries) { if (!entry->id) { return ::testing::AssertionFailure() - << "resource " << ResourceNameRef(package->name, type->type, entry->name) + << "resource " << ResourceNameRef(package->name, type->named_type, entry->name) << " has no ID"; } if (!seen_ids.insert(entry->id.value()).second) { return ::testing::AssertionFailure() - << "resource " << ResourceNameRef(package->name, type->type, entry->name) + << "resource " << ResourceNameRef(package->name, type->named_type, entry->name) << " has a non-unique ID" << std::hex << entry->id.value() << std::dec; } } diff --git a/tools/aapt2/format/binary/BinaryResourceParser.cpp b/tools/aapt2/format/binary/BinaryResourceParser.cpp index c65c55024bab..eea7efc449b9 100644 --- a/tools/aapt2/format/binary/BinaryResourceParser.cpp +++ b/tools/aapt2/format/binary/BinaryResourceParser.cpp @@ -18,19 +18,19 @@ #include <algorithm> #include <map> +#include <optional> #include <string> -#include "android-base/logging.h" -#include "android-base/macros.h" -#include "android-base/stringprintf.h" -#include "androidfw/ResourceTypes.h" -#include "androidfw/TypeWrappers.h" - #include "ResourceTable.h" #include "ResourceUtils.h" #include "ResourceValues.h" #include "Source.h" #include "ValueVisitor.h" +#include "android-base/logging.h" +#include "android-base/macros.h" +#include "android-base/stringprintf.h" +#include "androidfw/ResourceTypes.h" +#include "androidfw/TypeWrappers.h" #include "format/binary/ResChunkPullParser.h" #include "util/Util.h" @@ -364,7 +364,7 @@ bool BinaryResourceParser::ParseType(const ResourceTablePackage* package, config.copyFromDtoH(type->config); const std::string type_str = util::GetString(type_pool_, type->id - 1); - const ResourceType* parsed_type = ParseResourceType(type_str); + std::optional<ResourceNamedTypeRef> parsed_type = ParseResourceNamedType(type_str); if (!parsed_type) { diag_->Warn(DiagMessage(source_) << "invalid type name '" << type_str << "' for type with ID " << type->id); diff --git a/tools/aapt2/format/binary/TableFlattener.cpp b/tools/aapt2/format/binary/TableFlattener.cpp index a9192e889c17..b42e7d0c34cd 100644 --- a/tools/aapt2/format/binary/TableFlattener.cpp +++ b/tools/aapt2/format/binary/TableFlattener.cpp @@ -360,7 +360,7 @@ class PackageFlattener { if (!FlattenValue(&flat_entry, &values_buffer)) { diag_->Error(DiagMessage() << "failed to flatten resource '" - << ResourceNameRef(package_.name, type.type, flat_entry.entry->name) + << ResourceNameRef(package_.name, type.named_type, flat_entry.entry->name) << "' for configuration '" << config << "'"); return false; } @@ -447,7 +447,7 @@ class PackageFlattener { ResourceId id = android::make_resid(package_.id.value(), type.id.value(), entry.id.value()); CHECK(seen_ids.find(id) == seen_ids.end()) << "multiple overlayable definitions found for resource " - << ResourceName(package_.name, type.type, entry.name).to_string(); + << ResourceName(package_.name, type.named_type, entry.name).to_string(); seen_ids.insert(id); // Find the overlayable chunk with the specified name @@ -592,7 +592,8 @@ class PackageFlattener { bool FlattenTypes(BigBuffer* buffer) { size_t expected_type_id = 1; for (const ResourceTableTypeView& type : package_.types) { - if (type.type == ResourceType::kStyleable || type.type == ResourceType::kMacro) { + if (type.named_type.type == ResourceType::kStyleable || + type.named_type.type == ResourceType::kMacro) { // Styleables and macros are not real resource types. continue; } @@ -606,7 +607,7 @@ class PackageFlattener { expected_type_id++; } expected_type_id++; - type_pool_.MakeRef(to_string(type.type)); + type_pool_.MakeRef(type.named_type.to_string()); if (!FlattenTypeSpec(type, type.entries, buffer)) { return false; @@ -634,7 +635,7 @@ class PackageFlattener { } uint32_t local_key_index; - ResourceName resource_name({}, type.type, entry.name); + ResourceName resource_name({}, type.named_type, entry.name); if (!collapse_key_stringpool_ || name_collapse_exemptions_.find(resource_name) != name_collapse_exemptions_.end()) { local_key_index = (uint32_t)key_pool_.MakeRef(entry.name).index(); diff --git a/tools/aapt2/format/binary/TableFlattener_test.cpp b/tools/aapt2/format/binary/TableFlattener_test.cpp index cd1c0af702cf..c73bbb51f639 100644 --- a/tools/aapt2/format/binary/TableFlattener_test.cpp +++ b/tools/aapt2/format/binary/TableFlattener_test.cpp @@ -837,4 +837,45 @@ TEST_F(TableFlattenerTest, FlattenOverlayableNoPolicyFails) { ASSERT_FALSE(Flatten(context_.get(), {}, table.get(), &output_table)); } +TEST_F(TableFlattenerTest, FlattenCustomResourceTypes) { + std::unique_ptr<ResourceTable> table = + test::ResourceTableBuilder() + .AddSimple("com.app.test:id/one", ResourceId(0x7f010000)) + .AddSimple("com.app.test:id.2/two", ResourceId(0x7f020000)) + .AddValue("com.app.test:integer/one", ResourceId(0x7f030000), + util::make_unique<BinaryPrimitive>(uint8_t(Res_value::TYPE_INT_DEC), 10u)) + .AddValue("com.app.test:integer.1/one", ResourceId(0x7f040000), + util::make_unique<BinaryPrimitive>(uint8_t(Res_value::TYPE_INT_DEC), 1u)) + .AddValue("com.app.test:integer.1/one", test::ParseConfigOrDie("v1"), + ResourceId(0x7f040000), + util::make_unique<BinaryPrimitive>(uint8_t(Res_value::TYPE_INT_DEC), 2u)) + .AddString("com.app.test:layout.custom/bar", ResourceId(0x7f050000), "res/layout/bar.xml") + .Build(); + + ResTable res_table; + ASSERT_TRUE(Flatten(context_.get(), {}, table.get(), &res_table)); + + EXPECT_TRUE(Exists(&res_table, "com.app.test:id/one", ResourceId(0x7f010000), {}, + Res_value::TYPE_INT_BOOLEAN, 0u, 0u)); + + EXPECT_TRUE(Exists(&res_table, "com.app.test:id.2/two", ResourceId(0x7f020000), {}, + Res_value::TYPE_INT_BOOLEAN, 0u, 0u)); + + EXPECT_TRUE(Exists(&res_table, "com.app.test:integer/one", ResourceId(0x7f030000), {}, + Res_value::TYPE_INT_DEC, 10u, 0u)); + + EXPECT_TRUE(Exists(&res_table, "com.app.test:integer.1/one", ResourceId(0x7f040000), {}, + Res_value::TYPE_INT_DEC, 1u, ResTable_config::CONFIG_VERSION)); + + EXPECT_TRUE(Exists(&res_table, "com.app.test:integer.1/one", ResourceId(0x7f040000), + test::ParseConfigOrDie("v1"), Res_value::TYPE_INT_DEC, 2u, + ResTable_config::CONFIG_VERSION)); + + std::u16string bar_path = u"res/layout/bar.xml"; + auto idx = res_table.getTableStringBlock(0)->indexOfString(bar_path.data(), bar_path.size()); + ASSERT_TRUE(idx.has_value()); + EXPECT_TRUE(Exists(&res_table, "com.app.test:layout.custom/bar", ResourceId(0x7f050000), {}, + Res_value::TYPE_STRING, (uint32_t)*idx, 0u)); +} + } // namespace aapt diff --git a/tools/aapt2/format/proto/ProtoDeserialize.cpp b/tools/aapt2/format/proto/ProtoDeserialize.cpp index 236c38167545..82c7248f4b88 100644 --- a/tools/aapt2/format/proto/ProtoDeserialize.cpp +++ b/tools/aapt2/format/proto/ProtoDeserialize.cpp @@ -429,8 +429,8 @@ static bool DeserializePackageFromPb(const pb::Package& pb_package, const ResStr ResourceTablePackage* pkg = out_table->FindOrCreatePackage(pb_package.package_name()); for (const pb::Type& pb_type : pb_package.type()) { - const ResourceType* res_type = ParseResourceType(pb_type.name()); - if (res_type == nullptr) { + auto res_type = ParseResourceNamedType(pb_type.name()); + if (!res_type) { std::ostringstream error; error << "unknown type '" << pb_type.name() << "'"; *out_error = error.str(); @@ -515,7 +515,7 @@ static bool DeserializePackageFromPb(const pb::Package& pb_package, const ResStr ResourceId resid(pb_package.package_id().id(), pb_type.type_id().id(), pb_entry.entry_id().id()); if (resid.is_valid()) { - id_index[resid] = ResourceNameRef(pkg->name, type->type, entry->name); + id_index[resid] = ResourceNameRef(pkg->name, type->named_type, entry->name); } for (const pb::ConfigValue& pb_config_value : pb_entry.config_value()) { diff --git a/tools/aapt2/format/proto/ProtoSerialize.cpp b/tools/aapt2/format/proto/ProtoSerialize.cpp index f3b7f758e170..bb8ea0ce4f29 100644 --- a/tools/aapt2/format/proto/ProtoSerialize.cpp +++ b/tools/aapt2/format/proto/ProtoSerialize.cpp @@ -358,7 +358,7 @@ void SerializeTableToPb(const ResourceTable& table, pb::ResourceTable* out_table if (type.id) { pb_type->mutable_type_id()->set_id(type.id.value()); } - pb_type->set_name(to_string(type.type).to_string()); + pb_type->set_name(type.named_type.to_string()); // hardcoded string uses characters which make it an invalid resource name static const char* obfuscated_resource_name = "0_resource_name_obfuscated"; @@ -367,7 +367,7 @@ void SerializeTableToPb(const ResourceTable& table, pb::ResourceTable* out_table if (entry.id) { pb_entry->mutable_entry_id()->set_id(entry.id.value()); } - ResourceName resource_name({}, type.type, entry.name); + ResourceName resource_name({}, type.named_type, entry.name); if (options.collapse_key_stringpool && options.name_collapse_exemptions.find(resource_name) == options.name_collapse_exemptions.end()) { diff --git a/tools/aapt2/format/proto/ProtoSerialize_test.cpp b/tools/aapt2/format/proto/ProtoSerialize_test.cpp index d1d72e012b31..0247021f1f8a 100644 --- a/tools/aapt2/format/proto/ProtoSerialize_test.cpp +++ b/tools/aapt2/format/proto/ProtoSerialize_test.cpp @@ -951,4 +951,76 @@ TEST(ProtoSerializeTest, StagedId) { EXPECT_THAT(result.value().entry->staged_id.value().id, Eq(ResourceId(0x01ff0001))); } +TEST(ProtoSerializeTest, CustomResourceTypes) { + const uint32_t id_one_id = 0x7f020000; + const uint32_t id_2_two_id = 0x7f030000; + const uint32_t integer_three_id = 0x7f030000; + const uint32_t integer_1_four_id = 0x7f030000; + const uint32_t layout_bar_id = 0x7f050000; + std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); + std::unique_ptr<ResourceTable> table = + test::ResourceTableBuilder() + .AddSimple("com.app.test:id/one", ResourceId(id_one_id)) + .AddSimple("com.app.test:id.2/two", ResourceId(id_2_two_id)) + .AddValue( + "com.app.test:integer/one", ResourceId(integer_three_id), + util::make_unique<BinaryPrimitive>(uint8_t(android::Res_value::TYPE_INT_DEC), 10u)) + .AddValue( + "com.app.test:integer.1/one", ResourceId(integer_1_four_id), + util::make_unique<BinaryPrimitive>(uint8_t(android::Res_value::TYPE_INT_DEC), 1u)) + .AddValue( + "com.app.test:integer.1/one", test::ParseConfigOrDie("v1"), + ResourceId(integer_1_four_id), + util::make_unique<BinaryPrimitive>(uint8_t(android::Res_value::TYPE_INT_DEC), 2u)) + .AddFileReference("com.app.test:layout.custom/bar", ResourceId(layout_bar_id), + "res/layout/bar.xml") + .Build(); + + test::TestFile file_a("res/layout/bar.xml"); + MockFileCollection files; + EXPECT_CALL(files, FindFile(Eq("res/layout/bar.xml"))).WillRepeatedly(::testing::Return(&file_a)); + + ResourceTable new_table; + pb::ResourceTable pb_table; + std::string error; + SerializeTableToPb(*table, &pb_table, context->GetDiagnostics()); + DeserializeTableFromPb(pb_table, &files, &new_table, &error); + ASSERT_THAT(error, IsEmpty()); + + auto bp = test::GetValueForConfigAndProduct<BinaryPrimitive>( + &new_table, "com.app.test:integer.1/one", ConfigDescription::DefaultConfig(), ""); + ASSERT_THAT(bp, NotNull()); + EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_DEC)); + EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseInt("1")->value.data)); + + bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "com.app.test:integer.1/one", + test::ParseConfigOrDie("v1"), ""); + ASSERT_THAT(bp, NotNull()); + EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_DEC)); + EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseInt("2")->value.data)); + + bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "com.app.test:integer/one", + ConfigDescription::DefaultConfig(), ""); + ASSERT_THAT(bp, NotNull()); + EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_DEC)); + EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseInt("10")->value.data)); + + bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "com.app.test:integer/one", + test::ParseConfigOrDie("v1"), ""); + ASSERT_THAT(bp, IsNull()); + + auto id = test::GetValueForConfigAndProduct<Id>(&new_table, "com.app.test:id/one", + ConfigDescription::DefaultConfig(), ""); + ASSERT_THAT(id, NotNull()); + + id = test::GetValueForConfigAndProduct<Id>(&new_table, "com.app.test:id.2/two", + ConfigDescription::DefaultConfig(), ""); + ASSERT_THAT(id, NotNull()); + + auto custom_layout = test::GetValueForConfigAndProduct<FileReference>( + &new_table, "com.app.test:layout.custom/bar", ConfigDescription::DefaultConfig(), ""); + ASSERT_THAT(custom_layout, NotNull()); + EXPECT_THAT(*(custom_layout->path), Eq("res/layout/bar.xml")); +} + } // namespace aapt diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp index a963d9893f2f..a25ca22c288d 100644 --- a/tools/aapt2/java/JavaClassGenerator.cpp +++ b/tools/aapt2/java/JavaClassGenerator.cpp @@ -548,10 +548,11 @@ bool JavaClassGenerator::ProcessType(const StringPiece& package_name_to_generate } // We need to make sure we hide the fact that we are generating kAttrPrivate attributes. - const ResourceNameRef resource_name( - package_name_to_generate, - type.type == ResourceType::kAttrPrivate ? ResourceType::kAttr : type.type, - unmangled_name.value()); + const auto target_type = type.named_type.type == ResourceType::kAttrPrivate + ? ResourceNamedTypeWithDefaultName(ResourceType::kAttr) + : type.named_type; + const ResourceNameRef resource_name(package_name_to_generate, target_type, + unmangled_name.value()); // Check to see if the unmangled name is a valid Java name (not a keyword). if (!IsValidSymbol(unmangled_name.value())) { @@ -616,7 +617,8 @@ bool JavaClassGenerator::Generate(const StringPiece& package_name_to_generate, for (const auto& package : table_->packages) { for (const auto& type : package->types) { - if (type->type == ResourceType::kAttrPrivate || type->type == ResourceType::kMacro) { + if (type->named_type.type == ResourceType::kAttrPrivate || + type->named_type.type == ResourceType::kMacro) { // We generate kAttrPrivate as part of the kAttr type, so skip them here. // Macros are not actual resources, so skip them as well. continue; @@ -628,7 +630,7 @@ bool JavaClassGenerator::Generate(const StringPiece& package_name_to_generate, std::unique_ptr<ClassDefinition> class_def; if (out != nullptr) { class_def = util::make_unique<ClassDefinition>( - to_string(type->type), ClassQualifier::kStatic, force_creation_if_empty); + to_string(type->named_type.type), ClassQualifier::kStatic, force_creation_if_empty); } if (!ProcessType(package_name_to_generate, *package, *type, class_def.get(), @@ -636,9 +638,10 @@ bool JavaClassGenerator::Generate(const StringPiece& package_name_to_generate, return false; } - if (type->type == ResourceType::kAttr) { + if (type->named_type.type == ResourceType::kAttr) { // Also include private attributes in this same class. - if (const ResourceTableType* priv_type = package->FindType(ResourceType::kAttrPrivate)) { + if (const ResourceTableType* priv_type = + package->FindTypeWithDefaultName(ResourceType::kAttrPrivate)) { if (!ProcessType(package_name_to_generate, *package, *priv_type, class_def.get(), rewrite_method.get(), r_txt_printer.get())) { return false; @@ -646,7 +649,7 @@ bool JavaClassGenerator::Generate(const StringPiece& package_name_to_generate, } } - if (out != nullptr && type->type == ResourceType::kStyleable && is_public) { + if (out != nullptr && type->named_type.type == ResourceType::kStyleable && is_public) { // When generating a public R class, we don't want Styleable to be part // of the API. It is only emitted for documentation purposes. class_def->GetCommentBuilder()->AppendComment("@doconly"); diff --git a/tools/aapt2/java/ProguardRules.cpp b/tools/aapt2/java/ProguardRules.cpp index e53e22070b62..80a46d553960 100644 --- a/tools/aapt2/java/ProguardRules.cpp +++ b/tools/aapt2/java/ProguardRules.cpp @@ -517,7 +517,7 @@ bool CollectResourceReferences(aapt::IAaptContext* context, ResourceTable* table for (auto& type : pkg->types) { for (auto& entry : type->entries) { for (auto& config_value : entry->values) { - ResourceName from(pkg->name, type->type, entry->name); + ResourceName from(pkg->name, type->named_type, entry->name); ReferenceVisitor visitor(context, from, keep_set); config_value->value->Accept(&visitor); } diff --git a/tools/aapt2/link/AutoVersioner.cpp b/tools/aapt2/link/AutoVersioner.cpp index 328ac97090a8..3dbd7e613a3e 100644 --- a/tools/aapt2/link/AutoVersioner.cpp +++ b/tools/aapt2/link/AutoVersioner.cpp @@ -75,7 +75,7 @@ bool AutoVersioner::Consume(IAaptContext* context, ResourceTable* table) { CloningValueTransformer cloner(&table->string_pool); for (auto& package : table->packages) { for (auto& type : package->types) { - if (type->type != ResourceType::kStyle) { + if (type->named_type.type != ResourceType::kStyle) { continue; } diff --git a/tools/aapt2/link/NoDefaultResourceRemover.cpp b/tools/aapt2/link/NoDefaultResourceRemover.cpp index 05990de6a9b3..ab3c04e59741 100644 --- a/tools/aapt2/link/NoDefaultResourceRemover.cpp +++ b/tools/aapt2/link/NoDefaultResourceRemover.cpp @@ -76,7 +76,7 @@ bool NoDefaultResourceRemover::Consume(IAaptContext* context, ResourceTable* tab }); for (auto iter = remove_iter; iter != end_iter; ++iter) { - const ResourceName name(pkg->name, type->type, (*iter)->name); + const ResourceName name(pkg->name, type->named_type, (*iter)->name); IDiagnostics* diag = context->GetDiagnostics(); diag->Warn(DiagMessage() << "removing resource " << name << " without required default value"); diff --git a/tools/aapt2/link/PrivateAttributeMover.cpp b/tools/aapt2/link/PrivateAttributeMover.cpp index 675b02a7e161..8c6c743dfff0 100644 --- a/tools/aapt2/link/PrivateAttributeMover.cpp +++ b/tools/aapt2/link/PrivateAttributeMover.cpp @@ -57,7 +57,7 @@ OutputIterator move_if(InputContainer& input_container, OutputIterator result, P bool PrivateAttributeMover::Consume(IAaptContext* context, ResourceTable* table) { for (auto& package : table->packages) { - ResourceTableType* type = package->FindType(ResourceType::kAttr); + ResourceTableType* type = package->FindTypeWithDefaultName(ResourceType::kAttr); if (!type) { continue; } @@ -80,7 +80,8 @@ bool PrivateAttributeMover::Consume(IAaptContext* context, ResourceTable* table) continue; } - ResourceTableType* priv_attr_type = package->FindOrCreateType(ResourceType::kAttrPrivate); + auto attr_private_type = ResourceNamedTypeWithDefaultName(ResourceType::kAttrPrivate); + ResourceTableType* priv_attr_type = package->FindOrCreateType(attr_private_type); CHECK(priv_attr_type->entries.empty()); priv_attr_type->entries = std::move(private_attr_entries); } diff --git a/tools/aapt2/link/PrivateAttributeMover_test.cpp b/tools/aapt2/link/PrivateAttributeMover_test.cpp index 168234b36e4a..32335b7f5a9f 100644 --- a/tools/aapt2/link/PrivateAttributeMover_test.cpp +++ b/tools/aapt2/link/PrivateAttributeMover_test.cpp @@ -41,13 +41,13 @@ TEST(PrivateAttributeMoverTest, MovePrivateAttributes) { ResourceTablePackage* package = table->FindPackage("android"); ASSERT_NE(package, nullptr); - ResourceTableType* type = package->FindType(ResourceType::kAttr); + ResourceTableType* type = package->FindTypeWithDefaultName(ResourceType::kAttr); ASSERT_NE(type, nullptr); ASSERT_EQ(type->entries.size(), 2u); EXPECT_NE(type->FindEntry("publicA"), nullptr); EXPECT_NE(type->FindEntry("publicB"), nullptr); - type = package->FindType(ResourceType::kAttrPrivate); + type = package->FindTypeWithDefaultName(ResourceType::kAttrPrivate); ASSERT_NE(type, nullptr); ASSERT_EQ(type->entries.size(), 2u); EXPECT_NE(type->FindEntry("privateA"), nullptr); @@ -68,11 +68,11 @@ TEST(PrivateAttributeMoverTest, LeavePrivateAttributesWhenNoPublicAttributesDefi ResourceTablePackage* package = table->FindPackage("android"); ASSERT_NE(package, nullptr); - ResourceTableType* type = package->FindType(ResourceType::kAttr); + ResourceTableType* type = package->FindTypeWithDefaultName(ResourceType::kAttr); ASSERT_NE(type, nullptr); ASSERT_EQ(type->entries.size(), 2u); - type = package->FindType(ResourceType::kAttrPrivate); + type = package->FindTypeWithDefaultName(ResourceType::kAttrPrivate); ASSERT_EQ(type, nullptr); } @@ -87,12 +87,12 @@ TEST(PrivateAttributeMoverTest, DoNotCreatePrivateAttrsIfNoneExist) { ResourceTablePackage* package = table->FindPackage("android"); ASSERT_NE(nullptr, package); - ASSERT_EQ(nullptr, package->FindType(ResourceType::kAttrPrivate)); + ASSERT_EQ(nullptr, package->FindTypeWithDefaultName(ResourceType::kAttrPrivate)); PrivateAttributeMover mover; ASSERT_TRUE(mover.Consume(context.get(), table.get())); - ASSERT_EQ(nullptr, package->FindType(ResourceType::kAttrPrivate)); + ASSERT_EQ(nullptr, package->FindTypeWithDefaultName(ResourceType::kAttrPrivate)); } } // namespace aapt diff --git a/tools/aapt2/link/ProductFilter.cpp b/tools/aapt2/link/ProductFilter.cpp index 793740af3021..0c54a739d347 100644 --- a/tools/aapt2/link/ProductFilter.cpp +++ b/tools/aapt2/link/ProductFilter.cpp @@ -98,7 +98,7 @@ bool ProductFilter::Consume(IAaptContext* context, ResourceTable* table) { // End of the array, or we saw a different config, // so this must be the end of a range of products. // Select the product to keep from the set of products defined. - ResourceNameRef name(pkg->name, type->type, entry->name); + ResourceNameRef name(pkg->name, type->named_type, entry->name); auto value_to_keep = SelectProductToKeep( name, start_range_iter, iter, context->GetDiagnostics()); if (value_to_keep == iter) { diff --git a/tools/aapt2/link/ReferenceLinker.cpp b/tools/aapt2/link/ReferenceLinker.cpp index 5372cf243951..d1fbffa1debd 100644 --- a/tools/aapt2/link/ReferenceLinker.cpp +++ b/tools/aapt2/link/ReferenceLinker.cpp @@ -468,7 +468,7 @@ bool ReferenceLinker::Consume(IAaptContext* context, ResourceTable* table) { for (auto& type : package->types) { for (auto& entry : type->entries) { // First, unmangle the name if necessary. - ResourceName name(package->name, type->type, entry->name); + ResourceName name(package->name, type->named_type, entry->name); NameMangler::Unmangle(&name.entry, &name.package); // Symbol state information may be lost if there is no value for the resource. diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp index d78f0ac17f67..caaaba63931f 100644 --- a/tools/aapt2/link/TableMerger.cpp +++ b/tools/aapt2/link/TableMerger.cpp @@ -235,7 +235,7 @@ bool TableMerger::DoMerge(const Source& src, ResourceTablePackage* src_package, bool error = false; for (auto& src_type : src_package->types) { - ResourceTableType* dst_type = main_package_->FindOrCreateType(src_type->type); + ResourceTableType* dst_type = main_package_->FindOrCreateType(src_type->named_type); if (!MergeType(context_, src, dst_type, src_type.get())) { error = true; continue; @@ -254,7 +254,7 @@ bool TableMerger::DoMerge(const Source& src, ResourceTablePackage* src_package, dst_entry = dst_type->FindEntry(entry_name); } - const ResourceNameRef res_name(src_package->name, src_type->type, src_entry->name); + const ResourceNameRef res_name(src_package->name, src_type->named_type, src_entry->name); if (!dst_entry) { context_->GetDiagnostics()->Error(DiagMessage(src) @@ -349,7 +349,7 @@ bool TableMerger::MergeFile(const ResourceFile& file_desc, bool overlay, io::IFi file_ref->file = file; ResourceTablePackage* pkg = table.FindOrCreatePackage(file_desc.name.package); - pkg->FindOrCreateType(file_desc.name.type.type) + pkg->FindOrCreateType(file_desc.name.type) ->FindOrCreateEntry(file_desc.name.entry) ->FindOrCreateValue(file_desc.config, {}) ->value = std::move(file_ref); diff --git a/tools/aapt2/optimize/ResourceFilter.cpp b/tools/aapt2/optimize/ResourceFilter.cpp index 08c045bf68f7..db84b66ecd2d 100644 --- a/tools/aapt2/optimize/ResourceFilter.cpp +++ b/tools/aapt2/optimize/ResourceFilter.cpp @@ -28,7 +28,7 @@ bool ResourceFilter::Consume(IAaptContext* context, ResourceTable* table) { for (auto& package : table->packages) { for (auto& type : package->types) { for (auto it = type->entries.begin(); it != type->entries.end(); ) { - ResourceName resource = ResourceName({}, type->type, (*it)->name); + ResourceName resource = ResourceName({}, type->named_type, (*it)->name); if (exclude_list_.find(resource) != exclude_list_.end()) { it = type->entries.erase(it); } else { diff --git a/tools/aapt2/split/TableSplitter.cpp b/tools/aapt2/split/TableSplitter.cpp index 116b2ab9aa98..85d150f16b26 100644 --- a/tools/aapt2/split/TableSplitter.cpp +++ b/tools/aapt2/split/TableSplitter.cpp @@ -189,7 +189,7 @@ void TableSplitter::SplitTable(ResourceTable* original_table) { } for (auto& type : pkg->types) { - if (type->type == ResourceType::kMipmap) { + if (type->named_type.type == ResourceType::kMipmap) { // Always keep mipmaps. continue; } @@ -241,7 +241,7 @@ void TableSplitter::SplitTable(ResourceTable* original_table) { // Create the same resource structure in the split. We do this lazily because we might // not have actual values for each type/entry. ResourceTablePackage* split_pkg = split_table->FindPackage(pkg->name); - ResourceTableType* split_type = split_pkg->FindOrCreateType(type->type); + ResourceTableType* split_type = split_pkg->FindOrCreateType(type->named_type); split_type->visibility_level = type->visibility_level; ResourceEntry* split_entry = split_type->FindOrCreateEntry(entry->name); diff --git a/tools/lint/README.md b/tools/lint/README.md index b534b62cb395..c674d36431b7 100644 --- a/tools/lint/README.md +++ b/tools/lint/README.md @@ -78,6 +78,7 @@ adding `cmd.Flag("--nowarn")` and running lint again. ## Documentation - [Android Lint Docs](https://googlesamples.github.io/android-custom-lint-rules/) +- [Lint Check Unit Testing](https://googlesamples.github.io/android-custom-lint-rules/api-guide/unit-testing.md.html) - [Android Lint source files](https://source.corp.google.com/studio-main/tools/base/lint/libs/lint-api/src/main/java/com/android/tools/lint/) - [PSI source files](https://github.com/JetBrains/intellij-community/tree/master/java/java-psi-api/src/com/intellij/psi) - [UAST source files](https://upsource.jetbrains.com/idea-ce/structure/idea-ce-7b9b8cc138bbd90aec26433f82cd2c6838694003/uast/uast-common/src/org/jetbrains/uast) diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt b/tools/lint/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt index a6fd9bba6192..859961a2a079 100644 --- a/tools/lint/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt +++ b/tools/lint/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt @@ -19,6 +19,7 @@ package com.google.android.lint import com.android.tools.lint.client.api.IssueRegistry import com.android.tools.lint.client.api.Vendor import com.android.tools.lint.detector.api.CURRENT_API +import com.google.android.lint.parcel.SaferParcelChecker import com.google.auto.service.AutoService @AutoService(IssueRegistry::class) @@ -33,7 +34,8 @@ class AndroidFrameworkIssueRegistry : IssueRegistry() { CallingIdentityTokenDetector.ISSUE_CLEAR_IDENTITY_CALL_NOT_FOLLOWED_BY_TRY_FINALLY, CallingSettingsNonUserGetterMethodsDetector.ISSUE_NON_USER_GETTER_CALLED, EnforcePermissionDetector.ISSUE_MISSING_ENFORCE_PERMISSION, - EnforcePermissionDetector.ISSUE_MISMATCHING_ENFORCE_PERMISSION + EnforcePermissionDetector.ISSUE_MISMATCHING_ENFORCE_PERMISSION, + SaferParcelChecker.ISSUE_UNSAFE_API_USAGE, ) override val api: Int diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/EnforcePermissionDetector.kt b/tools/lint/checks/src/main/java/com/google/android/lint/EnforcePermissionDetector.kt index 8011b36c9a8f..9f216189ad62 100644 --- a/tools/lint/checks/src/main/java/com/google/android/lint/EnforcePermissionDetector.kt +++ b/tools/lint/checks/src/main/java/com/google/android/lint/EnforcePermissionDetector.kt @@ -16,6 +16,7 @@ package com.google.android.lint +import com.android.tools.lint.client.api.UElementHandler import com.android.tools.lint.detector.api.AnnotationInfo import com.android.tools.lint.detector.api.AnnotationOrigin import com.android.tools.lint.detector.api.AnnotationUsageInfo @@ -32,22 +33,39 @@ import com.android.tools.lint.detector.api.SourceCodeScanner import com.intellij.psi.PsiAnnotation import com.intellij.psi.PsiClass import com.intellij.psi.PsiMethod +import org.jetbrains.uast.UAnnotation import org.jetbrains.uast.UElement +import org.jetbrains.uast.UClass +import org.jetbrains.uast.UMethod /** * Lint Detector that ensures that any method overriding a method annotated * with @EnforcePermission is also annotated with the exact same annotation. * The intent is to surface the effective permission checks to the service * implementations. + * + * This is done with 2 mechanisms: + * 1. Visit any annotation usage, to ensure that any derived class will have + * the correct annotation on each methods. This is for the top to bottom + * propagation. + * 2. Visit any annotation, to ensure that if a method is annotated, it has + * its ancestor also annotated. This is to avoid having an annotation on a + * Java method without the corresponding annotation on the AIDL interface. */ class EnforcePermissionDetector : Detector(), SourceCodeScanner { val ENFORCE_PERMISSION = "android.annotation.EnforcePermission" + val BINDER_CLASS = "android.os.Binder" + val JAVA_OBJECT = "java.lang.Object" override fun applicableAnnotations(): List<String> { return listOf(ENFORCE_PERMISSION) } + override fun getApplicableUastTypes(): List<Class<out UElement>> { + return listOf(UAnnotation::class.java) + } + private fun areAnnotationsEquivalent( context: JavaContext, anno1: PsiAnnotation, @@ -74,6 +92,73 @@ class EnforcePermissionDetector : Detector(), SourceCodeScanner { return true } + private fun compareMethods( + context: JavaContext, + element: UElement, + overridingMethod: PsiMethod, + overriddenMethod: PsiMethod, + checkEquivalence: Boolean = true + ) { + val overridingAnnotation = overridingMethod.getAnnotation(ENFORCE_PERMISSION) + val overriddenAnnotation = overriddenMethod.getAnnotation(ENFORCE_PERMISSION) + val location = context.getLocation(element) + val overridingClass = overridingMethod.parent as PsiClass + val overriddenClass = overriddenMethod.parent as PsiClass + val overridingName = "${overridingClass.name}.${overridingMethod.name}" + val overriddenName = "${overriddenClass.name}.${overriddenMethod.name}" + if (overridingAnnotation == null) { + val msg = "The method $overridingName overrides the method $overriddenName which " + + "is annotated with @EnforcePermission. The same annotation must be used " + + "on $overridingName" + context.report(ISSUE_MISSING_ENFORCE_PERMISSION, element, location, msg) + } else if (overriddenAnnotation == null) { + val msg = "The method $overridingName overrides the method $overriddenName which " + + "is not annotated with @EnforcePermission. The same annotation must be " + + "used on $overriddenName. Did you forget to annotate the AIDL definition?" + context.report(ISSUE_MISSING_ENFORCE_PERMISSION, element, location, msg) + } else if (checkEquivalence && !areAnnotationsEquivalent( + context, overridingAnnotation, overriddenAnnotation)) { + val msg = "The method $overridingName is annotated with " + + "${overridingAnnotation.text} which differs from the overridden " + + "method $overriddenName: ${overriddenAnnotation.text}. The same " + + "annotation must be used for both methods." + context.report(ISSUE_MISMATCHING_ENFORCE_PERMISSION, element, location, msg) + } + } + + private fun compareClasses( + context: JavaContext, + element: UElement, + newClass: PsiClass, + extendedClass: PsiClass, + checkEquivalence: Boolean = true + ) { + val newAnnotation = newClass.getAnnotation(ENFORCE_PERMISSION) + val extendedAnnotation = extendedClass.getAnnotation(ENFORCE_PERMISSION) + + val location = context.getLocation(element) + val newClassName = newClass.qualifiedName + val extendedClassName = extendedClass.qualifiedName + if (newAnnotation == null) { + val msg = "The class $newClassName extends the class $extendedClassName which " + + "is annotated with @EnforcePermission. The same annotation must be used " + + "on $newClassName." + context.report(ISSUE_MISSING_ENFORCE_PERMISSION, element, location, msg) + } else if (extendedAnnotation == null) { + val msg = "The class $newClassName extends the class $extendedClassName which " + + "is not annotated with @EnforcePermission. The same annotation must be used " + + "on $extendedClassName. Did you forget to annotate the AIDL definition?" + context.report(ISSUE_MISSING_ENFORCE_PERMISSION, element, location, msg) + } else if (checkEquivalence && !areAnnotationsEquivalent( + context, newAnnotation, extendedAnnotation)) { + val msg = "The class $newClassName is annotated with ${newAnnotation.text} " + + "which differs from the parent class $extendedClassName: " + + "${extendedAnnotation.text}. The same annotation must be used for " + + "both classes." + context.report(ISSUE_MISMATCHING_ENFORCE_PERMISSION, element, location, msg) + } + } + override fun visitAnnotationUsage( context: JavaContext, element: UElement, @@ -83,48 +168,42 @@ class EnforcePermissionDetector : Detector(), SourceCodeScanner { if (usageInfo.type == AnnotationUsageType.EXTENDS) { val newClass = element.sourcePsi?.parent?.parent as PsiClass val extendedClass: PsiClass = usageInfo.referenced as PsiClass - val newAnnotation = newClass.getAnnotation(ENFORCE_PERMISSION) - val extendedAnnotation = extendedClass.getAnnotation(ENFORCE_PERMISSION)!! - - val location = context.getLocation(element) - val newClassName = newClass.qualifiedName - val extendedClassName = extendedClass.qualifiedName - if (newAnnotation == null) { - val msg = "The class $newClassName extends the class $extendedClassName which " + - "is annotated with @EnforcePermission. The same annotation must be used " + - "on $newClassName." - context.report(ISSUE_MISSING_ENFORCE_PERMISSION, element, location, msg) - } else if (!areAnnotationsEquivalent(context, newAnnotation, extendedAnnotation)) { - val msg = "The class $newClassName is annotated with ${newAnnotation.text} " + - "which differs from the parent class $extendedClassName: " + - "${extendedAnnotation.text}. The same annotation must be used for " + - "both classes." - context.report(ISSUE_MISMATCHING_ENFORCE_PERMISSION, element, location, msg) - } + compareClasses(context, element, newClass, extendedClass) } else if (usageInfo.type == AnnotationUsageType.METHOD_OVERRIDE && annotationInfo.origin == AnnotationOrigin.METHOD) { val overridingMethod = element.sourcePsi as PsiMethod val overriddenMethod = usageInfo.referenced as PsiMethod - val overridingAnnotation = overridingMethod.getAnnotation(ENFORCE_PERMISSION) - val overriddenAnnotation = overriddenMethod.getAnnotation(ENFORCE_PERMISSION)!! - - val location = context.getLocation(element) - val overridingClass = overridingMethod.parent as PsiClass - val overriddenClass = overriddenMethod.parent as PsiClass - val overridingName = "${overridingClass.name}.${overridingMethod.name}" - val overriddenName = "${overriddenClass.name}.${overriddenMethod.name}" - if (overridingAnnotation == null) { - val msg = "The method $overridingName overrides the method $overriddenName which " + - "is annotated with @EnforcePermission. The same annotation must be used " + - "on $overridingName" - context.report(ISSUE_MISSING_ENFORCE_PERMISSION, element, location, msg) - } else if (!areAnnotationsEquivalent( - context, overridingAnnotation, overriddenAnnotation)) { - val msg = "The method $overridingName is annotated with " + - "${overridingAnnotation.text} which differs from the overridden " + - "method $overriddenName: ${overriddenAnnotation.text}. The same " + - "annotation must be used for both methods." - context.report(ISSUE_MISMATCHING_ENFORCE_PERMISSION, element, location, msg) + compareMethods(context, element, overridingMethod, overriddenMethod) + } + } + + override fun createUastHandler(context: JavaContext): UElementHandler { + return object : UElementHandler() { + override fun visitAnnotation(node: UAnnotation) { + if (node.qualifiedName != ENFORCE_PERMISSION) { + return + } + val method = node.uastParent as? UMethod + val klass = node.uastParent as? UClass + if (klass != null) { + val newClass = klass as PsiClass + val extendedClass = newClass.getSuperClass() + if (extendedClass != null && extendedClass.qualifiedName != JAVA_OBJECT) { + // The equivalence check can be skipped, if both classes are + // annotated, it will be verified by visitAnnotationUsage. + compareClasses(context, klass, newClass, + extendedClass, checkEquivalence = false) + } + } else if (method != null) { + val overridingMethod = method as PsiMethod + val parents = overridingMethod.findSuperMethods() + for (overriddenMethod in parents) { + // The equivalence check can be skipped, if both methods are + // annotated, it will be verified by visitAnnotationUsage. + compareMethods(context, method, overridingMethod, + overriddenMethod, checkEquivalence = false) + } + } } } } diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/parcel/CallMigrators.kt b/tools/lint/checks/src/main/java/com/google/android/lint/parcel/CallMigrators.kt new file mode 100644 index 000000000000..cc2ab19c97f1 --- /dev/null +++ b/tools/lint/checks/src/main/java/com/google/android/lint/parcel/CallMigrators.kt @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.lint.parcel + +import com.android.tools.lint.detector.api.JavaContext +import com.android.tools.lint.detector.api.LintFix +import com.android.tools.lint.detector.api.Location +import com.intellij.psi.PsiCallExpression +import com.intellij.psi.PsiClassType +import com.intellij.psi.PsiIntersectionType +import com.intellij.psi.PsiMethod +import com.intellij.psi.PsiType +import com.intellij.psi.PsiTypeParameter +import com.intellij.psi.PsiWildcardType +import org.jetbrains.kotlin.utils.addToStdlib.cast +import org.jetbrains.uast.UCallExpression +import org.jetbrains.uast.UExpression +import org.jetbrains.uast.UVariable + +/** + * Subclass this class and override {@link #getBoundingClass} to report an unsafe Parcel API issue + * with a fix that migrates towards the new safer API by appending an argument in the form of + * {@code com.package.ItemType.class} coming from the result of the overridden method. + */ +abstract class CallMigrator( + val method: Method, + private val rejects: Set<String> = emptySet(), +) { + open fun report(context: JavaContext, call: UCallExpression, method: PsiMethod) { + val location = context.getLocation(call) + val itemType = getBoundingClass(context, call, method) + val fix = (itemType as? PsiClassType)?.let { type -> + getParcelFix(location, this.method.name, getArgumentSuffix(type)) + } + val message = "Unsafe `Parcel.${this.method.name}()` API usage" + context.report(SaferParcelChecker.ISSUE_UNSAFE_API_USAGE, call, location, message, fix) + } + + protected open fun getArgumentSuffix(type: PsiClassType) = + ", ${type.rawType().canonicalText}.class" + + protected open fun getBoundingClass( + context: JavaContext, + call: UCallExpression, + method: PsiMethod, + ): PsiType? = null + + protected fun getItemType(type: PsiType, container: String): PsiClassType? { + val supers = getParentTypes(type).mapNotNull { it as? PsiClassType } + val containerType = supers.firstOrNull { it.rawType().canonicalText == container } + ?: return null + val itemType = containerType.parameters.getOrNull(0) ?: return null + // TODO: Expand to other types, see PsiTypeVisitor + return when (itemType) { + is PsiClassType -> itemType + is PsiWildcardType -> itemType.bound as PsiClassType + else -> null + } + } + + /** + * Tries to obtain the type expected by the "receiving" end given a certain {@link UExpression}. + * + * This could be an assignment, an argument passed to a method call, to a constructor call, a + * type cast, etc. If no receiving end is found, the type of the UExpression itself is returned. + */ + protected fun getReceivingType(expression: UExpression): PsiType? { + val parent = expression.uastParent + val type = when (parent) { + is UCallExpression -> { + val i = parent.valueArguments.indexOf(expression) + val psiCall = parent.sourcePsi as? PsiCallExpression ?: return null + val typeSubstitutor = psiCall.resolveMethodGenerics().substitutor + val method = psiCall.resolveMethod()!! + method.getSignature(typeSubstitutor).parameterTypes[i] + } + is UVariable -> parent.type + is UExpression -> parent.getExpressionType() + else -> null + } + return filter(type ?: expression.getExpressionType()) + } + + private fun filter(type: PsiType?): PsiType? { + // It's important that PsiIntersectionType case is above the one that check the type in + // rejects, because for intersect types, the canonicalText is one of the terms. + if (type is PsiIntersectionType) { + return type.conjuncts.mapNotNull(this::filter).firstOrNull() + } + if (type == null || type.canonicalText in rejects) { + return null + } + if (type is PsiClassType && type.resolve() is PsiTypeParameter) { + return null + } + return type + } + + private fun getParentTypes(type: PsiType): Set<PsiType> = + type.superTypes.flatMap(::getParentTypes).toSet() + type + + protected fun getParcelFix(location: Location, method: String, arguments: String) = + LintFix + .create() + .name("Migrate to safer Parcel.$method() API") + .replace() + .range(location) + .pattern("$method\\s*\\(((?:.|\\n)*)\\)") + .with("\\k<1>$arguments") + .autoFix() + .build() +} + +/** + * This class derives the type to be appended by inferring the generic type of the {@code container} + * type (eg. "java.util.List") of the {@code argument}-th argument. + */ +class ContainerArgumentMigrator( + method: Method, + private val argument: Int, + private val container: String, + rejects: Set<String> = emptySet(), +) : CallMigrator(method, rejects) { + override fun getBoundingClass( + context: JavaContext, call: UCallExpression, method: PsiMethod + ): PsiType? { + val firstParamType = call.valueArguments[argument].getExpressionType() ?: return null + return getItemType(firstParamType, container)!! + } + + /** + * We need to insert a casting construct in the class parameter. For example: + * (Class<Foo<Bar>>) (Class<?>) Foo.class. + * This is needed for when the arguments of the conflict (eg. when there is List<Foo<Bar>> and + * class type is Class<Foo?). + */ + override fun getArgumentSuffix(type: PsiClassType): String { + if (type.parameters.isNotEmpty()) { + val rawType = type.rawType() + return ", (Class<${type.canonicalText}>) (Class<?>) ${rawType.canonicalText}.class" + } + return super.getArgumentSuffix(type) + } +} + +/** + * This class derives the type to be appended by inferring the generic type of the {@code container} + * type (eg. "java.util.List") of the return type of the method. + */ +class ContainerReturnMigrator( + method: Method, + private val container: String, + rejects: Set<String> = emptySet(), +) : CallMigrator(method, rejects) { + override fun getBoundingClass( + context: JavaContext, call: UCallExpression, method: PsiMethod + ): PsiType? { + val type = getReceivingType(call.uastParent as UExpression) ?: return null + return getItemType(type, container) + } +} + +/** + * This class derives the type to be appended by inferring the expected type for the method result. + */ +class ReturnMigrator( + method: Method, + rejects: Set<String> = emptySet(), +) : CallMigrator(method, rejects) { + override fun getBoundingClass( + context: JavaContext, call: UCallExpression, method: PsiMethod + ): PsiType? { + return getReceivingType(call.uastParent as UExpression) + } +} + +/** + * This class appends the class loader and the class object by deriving the type from the method + * result. + */ +class ReturnMigratorWithClassLoader( + method: Method, + rejects: Set<String> = emptySet(), +) : CallMigrator(method, rejects) { + override fun getBoundingClass( + context: JavaContext, call: UCallExpression, method: PsiMethod + ): PsiType? { + return getReceivingType(call.uastParent as UExpression) + } + + override fun getArgumentSuffix(type: PsiClassType): String = + "${type.rawType().canonicalText}.class.getClassLoader(), " + + "${type.rawType().canonicalText}.class" + +}
\ No newline at end of file diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/parcel/Method.kt b/tools/lint/checks/src/main/java/com/google/android/lint/parcel/Method.kt new file mode 100644 index 000000000000..c032fa29f254 --- /dev/null +++ b/tools/lint/checks/src/main/java/com/google/android/lint/parcel/Method.kt @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.lint.parcel + +data class Method( + val params: List<String>, + val clazz: String, + val name: String, + val parameters: List<String> +) { + constructor( + clazz: String, + name: String, + parameters: List<String> + ) : this( + listOf(), clazz, name, parameters + ) + + val signature: String + get() { + val prefix = if (params.isEmpty()) "" else "${params.joinToString(", ", "<", ">")} " + return "$prefix$clazz.$name(${parameters.joinToString()})" + } +}
\ No newline at end of file diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/parcel/SaferParcelChecker.kt b/tools/lint/checks/src/main/java/com/google/android/lint/parcel/SaferParcelChecker.kt new file mode 100644 index 000000000000..89dbcaeac3a7 --- /dev/null +++ b/tools/lint/checks/src/main/java/com/google/android/lint/parcel/SaferParcelChecker.kt @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.lint.parcel + +import com.android.tools.lint.detector.api.* +import com.intellij.psi.PsiMethod +import com.intellij.psi.PsiSubstitutor +import com.intellij.psi.PsiType +import com.intellij.psi.PsiTypeParameter +import org.jetbrains.uast.UCallExpression +import java.util.* + +class SaferParcelChecker : Detector(), SourceCodeScanner { + override fun getApplicableMethodNames(): List<String> = + MIGRATORS + .map(CallMigrator::method) + .map(Method::name) + + override fun visitMethodCall(context: JavaContext, node: UCallExpression, method: PsiMethod) { + if (!isAtLeastT(context)) return + val signature = getSignature(method) + val migrator = MIGRATORS.firstOrNull { it.method.signature == signature } ?: return + migrator.report(context, node, method) + } + + private fun getSignature(method: PsiMethod): String { + val name = UastLintUtils.getQualifiedName(method) + val signature = method.getSignature(PsiSubstitutor.EMPTY) + val parameters = + signature.parameterTypes.joinToString(transform = PsiType::getCanonicalText) + val types = signature.typeParameters.map(PsiTypeParameter::getName) + val prefix = if (types.isEmpty()) "" else types.joinToString(", ", "<", ">") + " " + return "$prefix$name($parameters)" + } + + /** Taken from androidx-main:core/core/src/main/java/androidx/core/os/BuildCompat.java */ + private fun isAtLeastT(context: Context): Boolean { + val project = if (context.isGlobalAnalysis()) context.mainProject else context.project + return project.isAndroidProject + && project.minSdkVersion.featureLevel >= 32 + && isAtLeastPreReleaseCodename("Tiramisu", project.minSdkVersion.codename) + } + + /** Taken from androidx-main:core/core/src/main/java/androidx/core/os/BuildCompat.java */ + private fun isAtLeastPreReleaseCodename(min: String, actual: String): Boolean { + if (actual == "REL") return false + return actual.uppercase(Locale.ROOT) >= min.uppercase(Locale.ROOT) + } + + companion object { + @JvmField + val ISSUE_UNSAFE_API_USAGE: Issue = Issue.create( + id = "UnsafeParcelApi", + briefDescription = "Use of unsafe Parcel API", + explanation = """ + You are using a deprecated Parcel API that doesn't accept the expected class as\ + a parameter. This means that unexpected classes could be instantiated and\ + unexpected code executed. + + Please migrate to the safer alternative that takes an extra Class<T> parameter. + """, + category = Category.SECURITY, + priority = 8, + severity = Severity.WARNING, + + implementation = Implementation( + SaferParcelChecker::class.java, + Scope.JAVA_FILE_SCOPE + ) + ) + + private val METHOD_READ_SERIALIZABLE = Method("android.os.Parcel", "readSerializable", listOf()) + private val METHOD_READ_ARRAY_LIST = Method("android.os.Parcel", "readArrayList", listOf("java.lang.ClassLoader")) + private val METHOD_READ_LIST = Method("android.os.Parcel", "readList", listOf("java.util.List", "java.lang.ClassLoader")) + private val METHOD_READ_PARCELABLE = Method(listOf("T"), "android.os.Parcel", "readParcelable", listOf("java.lang.ClassLoader")) + private val METHOD_READ_PARCELABLE_LIST = Method(listOf("T"), "android.os.Parcel", "readParcelableList", listOf("java.util.List<T>", "java.lang.ClassLoader")) + private val METHOD_READ_SPARSE_ARRAY = Method(listOf("T"), "android.os.Parcel", "readSparseArray", listOf("java.lang.ClassLoader")) + + // TODO: Write migrators for methods below + private val METHOD_READ_ARRAY = Method("android.os.Parcel", "readArray", listOf("java.lang.ClassLoader")) + private val METHOD_READ_PARCELABLE_ARRAY = Method("android.os.Parcel", "readParcelableArray", listOf("java.lang.ClassLoader")) + private val METHOD_READ_PARCELABLE_CREATOR = Method("android.os.Parcel", "readParcelableCreator", listOf("java.lang.ClassLoader")) + + private val MIGRATORS = listOf( + ReturnMigrator(METHOD_READ_PARCELABLE, setOf("android.os.Parcelable")), + ContainerArgumentMigrator(METHOD_READ_LIST, 0, "java.util.List"), + ContainerReturnMigrator(METHOD_READ_ARRAY_LIST, "java.util.Collection"), + ContainerReturnMigrator(METHOD_READ_SPARSE_ARRAY, "android.util.SparseArray"), + ContainerArgumentMigrator(METHOD_READ_PARCELABLE_LIST, 0, "java.util.List"), + ReturnMigratorWithClassLoader(METHOD_READ_SERIALIZABLE), + ) + } +}
\ No newline at end of file diff --git a/tools/lint/checks/src/test/java/com/google/android/lint/EnforcePermissionDetectorTest.kt b/tools/lint/checks/src/test/java/com/google/android/lint/EnforcePermissionDetectorTest.kt index f5f4ebee24e0..2cfc3fbcefcb 100644 --- a/tools/lint/checks/src/test/java/com/google/android/lint/EnforcePermissionDetectorTest.kt +++ b/tools/lint/checks/src/test/java/com/google/android/lint/EnforcePermissionDetectorTest.kt @@ -147,14 +147,57 @@ annotation must be used on TestClass6.testMethod [MissingEnforcePermissionAnnota 1 errors, 0 warnings""".addLineContinuation()) } + fun testDetectIssuesExtraAnnotationMethod() { + lint().files(java( + """ + package test.pkg; + public class TestClass7 extends IBar.Stub { + @android.annotation.EnforcePermission(android.Manifest.permission.INTERNET) + public void testMethod() {} + } + """).indented(), + *stubs + ) + .run() + .expect("""src/test/pkg/TestClass7.java:4: Error: The method TestClass7.testMethod \ +overrides the method Stub.testMethod which is not annotated with @EnforcePermission. The same \ +annotation must be used on Stub.testMethod. Did you forget to annotate the AIDL definition? \ +[MissingEnforcePermissionAnnotation] + public void testMethod() {} + ~~~~~~~~~~ +1 errors, 0 warnings""".addLineContinuation()) + } + + fun testDetectIssuesExtraAnnotationInterface() { + lint().files(java( + """ + package test.pkg; + @android.annotation.EnforcePermission(android.Manifest.permission.INTERNET) + public class TestClass8 extends IBar.Stub { + public void testMethod() {} + } + """).indented(), + *stubs + ) + .run() + .expect("""src/test/pkg/TestClass8.java:2: Error: The class test.pkg.TestClass8 \ +extends the class IBar.Stub which is not annotated with @EnforcePermission. The same annotation \ +must be used on IBar.Stub. Did you forget to annotate the AIDL definition? \ +[MissingEnforcePermissionAnnotation] +@android.annotation.EnforcePermission(android.Manifest.permission.INTERNET) +^ +1 errors, 0 warnings""".addLineContinuation()) + } + /* Stubs */ + // A service with permission annotation on the class. private val interfaceIFooStub: TestFile = java( """ @android.annotation.EnforcePermission(android.Manifest.permission.READ_PHONE_STATE) public interface IFoo { @android.annotation.EnforcePermission(android.Manifest.permission.READ_PHONE_STATE) - public static abstract class Stub implements IFoo { + public static abstract class Stub extends android.os.Binder implements IFoo { @Override public void testMethod() {} } @@ -163,10 +206,11 @@ annotation must be used on TestClass6.testMethod [MissingEnforcePermissionAnnota """ ).indented() + // A service with permission annotation on the method. private val interfaceIFooMethodStub: TestFile = java( """ public interface IFooMethod { - public static abstract class Stub implements IFooMethod { + public static abstract class Stub extends android.os.Binder implements IFooMethod { @Override @android.annotation.EnforcePermission(android.Manifest.permission.READ_PHONE_STATE) public void testMethod() {} @@ -177,6 +221,19 @@ annotation must be used on TestClass6.testMethod [MissingEnforcePermissionAnnota """ ).indented() + // A service without any permission annotation. + private val interfaceIBarStub: TestFile = java( + """ + public interface IBar { + public static abstract class Stub extends android.os.Binder implements IBar { + @Override + public void testMethod() {} + } + public void testMethod(); + } + """ + ).indented() + private val manifestPermissionStub: TestFile = java( """ package android.Manifest; @@ -194,7 +251,7 @@ annotation must be used on TestClass6.testMethod [MissingEnforcePermissionAnnota """ ).indented() - private val stubs = arrayOf(interfaceIFooStub, interfaceIFooMethodStub, + private val stubs = arrayOf(interfaceIFooStub, interfaceIFooMethodStub, interfaceIBarStub, manifestPermissionStub, enforcePermissionAnnotationStub) // Substitutes "backslash + new line" with an empty string to imitate line continuation diff --git a/tools/lint/checks/src/test/java/com/google/android/lint/parcel/SaferParcelCheckerTest.kt b/tools/lint/checks/src/test/java/com/google/android/lint/parcel/SaferParcelCheckerTest.kt new file mode 100644 index 000000000000..05c7850c44c2 --- /dev/null +++ b/tools/lint/checks/src/test/java/com/google/android/lint/parcel/SaferParcelCheckerTest.kt @@ -0,0 +1,428 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.lint.parcel + +import com.android.tools.lint.checks.infrastructure.LintDetectorTest +import com.android.tools.lint.checks.infrastructure.TestLintTask +import com.android.tools.lint.checks.infrastructure.TestMode +import com.android.tools.lint.detector.api.Detector +import com.android.tools.lint.detector.api.Issue + +@Suppress("UnstableApiUsage") +class SaferParcelCheckerTest : LintDetectorTest() { + override fun getDetector(): Detector = SaferParcelChecker() + + override fun getIssues(): List<Issue> = listOf( + SaferParcelChecker.ISSUE_UNSAFE_API_USAGE + ) + + override fun lint(): TestLintTask = + super.lint() + .allowMissingSdk(true) + // We don't do partial analysis in the platform + .skipTestModes(TestMode.PARTIAL) + + fun testDetectUnsafeReadSerializable() { + lint() + .files( + java( + """ + package test.pkg; + import android.os.Parcel; + import java.io.Serializable; + + public class TestClass { + private TestClass(Parcel p) { + Serializable ans = p.readSerializable(); + } + } + """ + ).indented(), + *includes + ) + .expectIdenticalTestModeOutput(false) + .run() + .expect( + """ + src/test/pkg/TestClass.java:7: Warning: Unsafe Parcel.readSerializable() \ + API usage [UnsafeParcelApi] + Serializable ans = p.readSerializable(); + ~~~~~~~~~~~~~~~~~~~~ + 0 errors, 1 warnings + """.addLineContinuation() + ) + } + + fun testDoesNotDetectSafeReadSerializable() { + lint() + .files( + java( + """ + package test.pkg; + import android.os.Parcel; + import java.io.Serializable; + + public class TestClass { + private TestClass(Parcel p) { + String ans = p.readSerializable(null, String.class); + } + } + """ + ).indented(), + *includes + ) + .run() + .expect("No warnings.") + } + + fun testDetectUnsafeReadArrayList() { + lint() + .files( + java( + """ + package test.pkg; + import android.os.Parcel; + + public class TestClass { + private TestClass(Parcel p) { + ArrayList ans = p.readArrayList(null); + } + } + """ + ).indented(), + *includes + ) + .run() + .expect( + """ + src/test/pkg/TestClass.java:6: Warning: Unsafe Parcel.readArrayList() API \ + usage [UnsafeParcelApi] + ArrayList ans = p.readArrayList(null); + ~~~~~~~~~~~~~~~~~~~~~ + 0 errors, 1 warnings + """.addLineContinuation() + ) + } + + fun testDoesNotDetectSafeReadArrayList() { + lint() + .files( + java( + """ + package test.pkg; + import android.content.Intent; + import android.os.Parcel; + + public class TestClass { + private TestClass(Parcel p) { + ArrayList<Intent> ans = p.readArrayList(null, Intent.class); + } + } + """ + ).indented(), + *includes + ) + .run() + .expect("No warnings.") + } + + fun testDetectUnsafeReadList() { + lint() + .files( + java( + """ + package test.pkg; + import android.content.Intent; + import android.os.Parcel; + import java.util.List; + + public class TestClass { + private TestClass(Parcel p) { + List<Intent> list = new ArrayList<Intent>(); + p.readList(list, null); + } + } + """ + ).indented(), + *includes + ) + .run() + .expect( + """ + src/test/pkg/TestClass.java:9: Warning: Unsafe Parcel.readList() API usage \ + [UnsafeParcelApi] + p.readList(list, null); + ~~~~~~~~~~~~~~~~~~~~~~ + 0 errors, 1 warnings + """.addLineContinuation() + ) + } + + fun testDoesNotDetectSafeReadList() { + lint() + .files( + java( + """ + package test.pkg; + import android.content.Intent; + import android.os.Parcel; + import java.util.List; + + public class TestClass { + private TestClass(Parcel p) { + List<Intent> list = new ArrayList<Intent>(); + p.readList(list, null, Intent.class); + } + } + """ + ).indented(), + *includes + ) + .run() + .expect("No warnings.") + } + + fun testDetectUnsafeReadParcelable() { + lint() + .files( + java( + """ + package test.pkg; + import android.content.Intent; + import android.os.Parcel; + + public class TestClass { + private TestClass(Parcel p) { + Intent ans = p.readParcelable(null); + } + } + """ + ).indented(), + *includes + ) + .run() + .expect( + """ + src/test/pkg/TestClass.java:7: Warning: Unsafe Parcel.readParcelable() API \ + usage [UnsafeParcelApi] + Intent ans = p.readParcelable(null); + ~~~~~~~~~~~~~~~~~~~~~~ + 0 errors, 1 warnings + """.addLineContinuation() + ) + } + + fun testDoesNotDetectSafeReadParcelable() { + lint() + .files( + java( + """ + package test.pkg; + import android.content.Intent; + import android.os.Parcel; + + public class TestClass { + private TestClass(Parcel p) { + Intent ans = p.readParcelable(null, Intent.class); + } + } + """ + ).indented(), + *includes + ) + .run() + .expect("No warnings.") + } + + fun testDetectUnsafeReadParcelableList() { + lint() + .files( + java( + """ + package test.pkg; + import android.content.Intent; + import android.os.Parcel; + import java.util.List; + + public class TestClass { + private TestClass(Parcel p) { + List<Intent> list = new ArrayList<Intent>(); + List<Intent> ans = p.readParcelableList(list, null); + } + } + """ + ).indented(), + *includes + ) + .run() + .expect( + """ + src/test/pkg/TestClass.java:9: Warning: Unsafe Parcel.readParcelableList() \ + API usage [UnsafeParcelApi] + List<Intent> ans = p.readParcelableList(list, null); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 0 errors, 1 warnings + """.addLineContinuation() + ) + } + + fun testDoesNotDetectSafeReadParcelableList() { + lint() + .files( + java( + """ + package test.pkg; + import android.content.Intent; + import android.os.Parcel; + import java.util.List; + + public class TestClass { + private TestClass(Parcel p) { + List<Intent> list = new ArrayList<Intent>(); + List<Intent> ans = + p.readParcelableList(list, null, Intent.class); + } + } + """ + ).indented(), + *includes + ) + .run() + .expect("No warnings.") + } + + fun testDetectUnsafeReadSparseArray() { + lint() + .files( + java( + """ + package test.pkg; + import android.content.Intent; + import android.os.Parcel; + import android.util.SparseArray; + + public class TestClass { + private TestClass(Parcel p) { + SparseArray<Intent> ans = p.readSparseArray(null); + } + } + """ + ).indented(), + *includes + ) + .run() + .expect( + """ + src/test/pkg/TestClass.java:8: Warning: Unsafe Parcel.readSparseArray() API\ + usage [UnsafeParcelApi] + SparseArray<Intent> ans = p.readSparseArray(null); + ~~~~~~~~~~~~~~~~~~~~~~~ + 0 errors, 1 warnings + """.addLineContinuation() + ) + } + + fun testDoesNotDetectSafeReadSparseArray() { + lint() + .files( + java( + """ + package test.pkg; + import android.content.Intent; + import android.os.Parcel; + import android.util.SparseArray; + + public class TestClass { + private TestClass(Parcel p) { + SparseArray<Intent> ans = + p.readSparseArray(null, Intent.class); + } + } + """ + ).indented(), + *includes + ) + .run() + .expect("No warnings.") + } + + /** Stubs for classes used for testing */ + + + private val includes = + arrayOf( + manifest().minSdk("Tiramisu"), + java( + """ + package android.os; + import java.util.ArrayList; + import java.util.List; + import java.util.Map; + import java.util.HashMap; + + public final class Parcel { + // Deprecateds + public Object[] readArray(ClassLoader loader) { return null; } + public ArrayList readArrayList(ClassLoader loader) { return null; } + public HashMap readHashMap(ClassLoader loader) { return null; } + public void readList(List outVal, ClassLoader loader) {} + public void readMap(Map outVal, ClassLoader loader) {} + public <T extends Parcelable> T readParcelable(ClassLoader loader) { return null; } + public Parcelable[] readParcelableArray(ClassLoader loader) { return null; } + public Parcelable.Creator<?> readParcelableCreator(ClassLoader loader) { return null; } + public <T extends Parcelable> List<T> readParcelableList(List<T> list, ClassLoader cl) { return null; } + public Serializable readSerializable() { return null; } + public <T> SparseArray<T> readSparseArray(ClassLoader loader) { return null; } + + // Replacements + public <T> T[] readArray(ClassLoader loader, Class<T> clazz) { return null; } + public <T> ArrayList<T> readArrayList(ClassLoader loader, Class<? extends T> clazz) { return null; } + public <K, V> HashMap<K,V> readHashMap(ClassLoader loader, Class<? extends K> clazzKey, Class<? extends V> clazzValue) { return null; } + public <T> void readList(List<? super T> outVal, ClassLoader loader, Class<T> clazz) {} + public <K, V> void readMap(Map<? super K, ? super V> outVal, ClassLoader loader, Class<K> clazzKey, Class<V> clazzValue) {} + public <T> T readParcelable(ClassLoader loader, Class<T> clazz) { return null; } + public <T> T[] readParcelableArray(ClassLoader loader, Class<T> clazz) { return null; } + public <T> Parcelable.Creator<T> readParcelableCreator(ClassLoader loader, Class<T> clazz) { return null; } + public <T> List<T> readParcelableList(List<T> list, ClassLoader cl, Class<T> clazz) { return null; } + public <T> T readSerializable(ClassLoader loader, Class<T> clazz) { return null; } + public <T> SparseArray<T> readSparseArray(ClassLoader loader, Class<? extends T> clazz) { return null; } + } + """ + ).indented(), + java( + """ + package android.os; + public interface Parcelable {} + """ + ).indented(), + java( + """ + package android.content; + public class Intent implements Parcelable, Cloneable {} + """ + ).indented(), + java( + """ + package android.util; + public class SparseArray<E> implements Cloneable {} + """ + ).indented(), + ) + + // Substitutes "backslash + new line" with an empty string to imitate line continuation + private fun String.addLineContinuation(): String = this.trimIndent().replace("\\\n", "") +} diff --git a/tools/preload-check/device/src/com/android/preload/check/Util.java b/tools/preload-check/device/src/com/android/preload/check/Util.java index fccea0a0c107..f521c95839f1 100644 --- a/tools/preload-check/device/src/com/android/preload/check/Util.java +++ b/tools/preload-check/device/src/com/android/preload/check/Util.java @@ -25,8 +25,8 @@ import java.io.FileOutputStream; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.URL; +import java.util.ArrayList; import java.util.Collection; -import java.util.LinkedList; import java.util.List; public class Util { @@ -48,7 +48,7 @@ public class Util { Class<?> vmClassLoaderClass = Class.forName("java.lang.VMClassLoader"); Method getResources = vmClassLoaderClass.getDeclaredMethod("getResources", String.class); getResources.setAccessible(true); - LinkedList<DexFile> res = new LinkedList<>(); + ArrayList<DexFile> res = new ArrayList<>(); for (int i = 1;; i++) { try { String name = "classes" + (i > 1 ? String.valueOf(i) : "") + ".dex"; |