diff options
802 files changed, 12920 insertions, 3903 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/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 52f883b5fbb7..50c2e75c3a01 100644 --- a/cmds/telecom/src/com/android/commands/telecom/Telecom.java +++ b/cmds/telecom/src/com/android/commands/telecom/Telecom.java @@ -52,7 +52,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"; @@ -286,7 +286,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."); } @@ -316,7 +316,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."); } @@ -358,7 +358,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."); } @@ -395,11 +395,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 b08ffc90a00d..c5ab512cfb3b 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); @@ -32341,6 +32345,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 +32357,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 +32374,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 +32729,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 { @@ -44254,6 +44294,9 @@ package android.telephony.ims { method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback); method public void unregisterImsStateCallback(@NonNull android.telephony.ims.ImsStateCallback); field public static final String ACTION_SHOW_CAPABILITY_DISCOVERY_OPT_IN = "android.telephony.ims.action.SHOW_CAPABILITY_DISCOVERY_OPT_IN"; + field public static final int CAPABILITY_TYPE_NONE = 0; // 0x0 + field public static final int CAPABILITY_TYPE_OPTIONS_UCE = 1; // 0x1 + field public static final int CAPABILITY_TYPE_PRESENCE_UCE = 2; // 0x2 } public final class ImsReasonInfo implements android.os.Parcelable { @@ -44475,10 +44518,10 @@ package android.telephony.ims { method public void unregisterFeatureProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.FeatureProvisioningCallback); } - public static class ProvisioningManager.FeatureProvisioningCallback { + public abstract static class ProvisioningManager.FeatureProvisioningCallback { ctor public ProvisioningManager.FeatureProvisioningCallback(); - method public void onFeatureProvisioningChanged(int, int, boolean); - method public void onRcsFeatureProvisioningChanged(int, int, boolean); + method public abstract void onFeatureProvisioningChanged(int, int, boolean); + method public abstract void onRcsFeatureProvisioningChanged(int, int, boolean); } public class RcsUceAdapter { @@ -44521,15 +44564,6 @@ package android.telephony.ims.feature { field public static final int CAPABILITY_TYPE_VOICE = 1; // 0x1 } - public class RcsFeature { - } - - public static class RcsFeature.RcsImsCapabilities { - field public static final int CAPABILITY_TYPE_NONE = 0; // 0x0 - field public static final int CAPABILITY_TYPE_OPTIONS_UCE = 1; // 0x1 - field public static final int CAPABILITY_TYPE_PRESENCE_UCE = 2; // 0x2 - } - } package android.telephony.ims.stub { @@ -48132,7 +48166,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(); @@ -52512,6 +52546,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(); @@ -52537,6 +52572,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); @@ -52557,6 +52593,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); @@ -52944,10 +52984,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 650de2e00c3b..03b4aa52e69a 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(); @@ -15024,7 +15029,7 @@ package android.telephony.ims { method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE, android.Manifest.permission.READ_CONTACTS}) public void requestAvailability(@NonNull android.net.Uri, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RcsUceAdapter.CapabilitiesCallback) throws android.telephony.ims.ImsException; method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE, android.Manifest.permission.READ_CONTACTS}) public void requestCapabilities(@NonNull java.util.Collection<android.net.Uri>, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RcsUceAdapter.CapabilitiesCallback) throws android.telephony.ims.ImsException; method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUceSettingEnabled(boolean) throws android.telephony.ims.ImsException; - field public static final int CAPABILITY_TYPE_PRESENCE_UCE = 2; // 0x2 + field @Deprecated public static final int CAPABILITY_TYPE_PRESENCE_UCE = 2; // 0x2 field public static final int CAPABILITY_UPDATE_TRIGGER_ETAG_EXPIRED = 1; // 0x1 field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_2G = 7; // 0x7 field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_3G = 6; // 0x6 @@ -15307,6 +15312,9 @@ package android.telephony.ims.feature { method public void addCapabilities(int); method public boolean isCapable(int); method public void removeCapabilities(int); + field public static final int CAPABILITY_TYPE_NONE = 0; // 0x0 + field public static final int CAPABILITY_TYPE_OPTIONS_UCE = 1; // 0x1 + field public static final int CAPABILITY_TYPE_PRESENCE_UCE = 2; // 0x2 } } 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 27f5b926411c..37edc03ca9d3 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -36,7 +36,6 @@ package android { field public static final String READ_PRIVILEGED_PHONE_STATE = "android.permission.READ_PRIVILEGED_PHONE_STATE"; field public static final String RECORD_BACKGROUND_AUDIO = "android.permission.RECORD_BACKGROUND_AUDIO"; field public static final String REMOVE_TASKS = "android.permission.REMOVE_TASKS"; - field public static final String REQUEST_UNIQUE_ID_ATTESTATION = "android.permission.REQUEST_UNIQUE_ID_ATTESTATION"; field public static final String RESET_APP_ERRORS = "android.permission.RESET_APP_ERRORS"; field public static final String REVOKE_POST_NOTIFICATIONS_WITHOUT_KILL = "android.permission.REVOKE_POST_NOTIFICATIONS_WITHOUT_KILL"; field public static final String SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS = "android.permission.SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS"; @@ -1250,10 +1249,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 +1858,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 +1871,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 +1888,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 +2074,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 { @@ -2467,6 +2432,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>); } @@ -2826,6 +2793,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 0a18588e0131..ea80369983a5 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -2023,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()); 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/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/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/InputManager.java b/core/java/android/hardware/input/InputManager.java index cc5b275bbf5a..f59b9f7debe1 100644 --- a/core/java/android/hardware/input/InputManager.java +++ b/core/java/android/hardware/input/InputManager.java @@ -272,8 +272,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 +333,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 +1393,7 @@ public final class InputManager { * </p> * @hide */ + @TestApi public void addUniqueIdAssociation(@NonNull String inputPort, @NonNull String displayUniqueId) { try { mIm.addUniqueIdAssociation(inputPort, displayUniqueId); @@ -1393,6 +1410,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/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/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 d8d9c7fc259e..a3227b712e6e 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -4519,13 +4519,6 @@ public final class Settings { public static final String SCREEN_OFF_TIMEOUT = "screen_off_timeout"; /** - * The amount of time in milliseconds before the device goes to sleep or begins to dream - * after a period of inactivity while it is docked. - * @hide - */ - public static final String SCREEN_OFF_TIMEOUT_DOCKED = "screen_off_timeout_docked"; - - /** * The screen backlight brightness between 0 and 255. */ @Readable @@ -10905,6 +10898,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 @@ -17251,6 +17252,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 */ @@ -17468,6 +17475,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/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 dfe0f542b3ca..19e248fc5cf5 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 8b9a86b9eec6..88449f53236d 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -31408,6 +31408,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 a3d0bf79416b..f310e7f7b185 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -890,8 +890,10 @@ public final class ViewRootImpl implements ViewParent, mChoreographer = 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); diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java index 0008aa64efa4..af8a017eb66e 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 b05b7916d960..92cf74519fbf 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; @@ -624,6 +639,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. @@ -1952,6 +1972,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) { @@ -2012,6 +2058,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, @@ -2365,6 +2418,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 */ @@ -3852,6 +3927,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 805f8e7551a5..52d88d6f2906 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -2918,7 +2918,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 54c0d7c9af32..9e1bc8f54212 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( @@ -9391,6 +9410,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) @@ -9403,7 +9425,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); @@ -9507,6 +9529,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) @@ -9519,7 +9544,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); @@ -9877,7 +9902,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()) @@ -9888,7 +9915,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..b19ac2fec640 100644 --- a/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java +++ b/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java @@ -18,6 +18,7 @@ package com.android.internal.app; import static android.app.prediction.AppTargetEvent.ACTION_LAUNCH; +import android.annotation.Nullable; import android.app.prediction.AppPredictor; import android.app.prediction.AppTarget; import android.app.prediction.AppTargetEvent; @@ -33,12 +34,11 @@ import android.util.Log; import com.android.internal.app.ResolverActivity.ResolvedComponentInfo; import java.util.ArrayList; +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 @@ -58,7 +58,9 @@ class AppPredictionServiceResolverComparator extends AbstractResolverComparator private final String mReferrerPackage; // 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; + private AppPredictionServiceComparatorModel mComparatorModel; AppPredictionServiceResolverComparator( Context context, @@ -74,25 +76,12 @@ class AppPredictionServiceResolverComparator extends AbstractResolverComparator mUser = user; mReferrerPackage = referrerPackage; setChooserActivityLogger(chooserActivityLogger); + mComparatorModel = buildUpdatedModel(); } @Override int compare(ResolveInfo lhs, ResolveInfo rhs) { - if (mResolverRankerService != null) { - return mResolverRankerService.compare(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; + return mComparatorModel.getComparator().compare(lhs, rhs); } @Override @@ -121,6 +110,7 @@ class AppPredictionServiceResolverComparator extends AbstractResolverComparator mContext, mIntent, mReferrerPackage, () -> mHandler.sendEmptyMessage(RANKER_SERVICE_RESULT), getChooserActivityLogger()); + mComparatorModel = buildUpdatedModel(); mResolverRankerService.compute(targets); } else { Log.i(TAG, "AppPredictionService response received"); @@ -163,6 +153,7 @@ class AppPredictionServiceResolverComparator extends AbstractResolverComparator mTargetRanks.put(componentName, i); Log.i(TAG, "handleSortedAppTargets, sortedAppTargets #" + i + ": " + componentName); } + mComparatorModel = buildUpdatedModel(); } private boolean checkAppTargetRankValid(List<AppTarget> sortedAppTargets) { @@ -176,43 +167,12 @@ class AppPredictionServiceResolverComparator extends AbstractResolverComparator @Override float getScore(ComponentName name) { - if (mResolverRankerService != null) { - return mResolverRankerService.getScore(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 - List<ComponentName> getTopComponentNames(int topK) { - if (mResolverRankerService != null) { - return mResolverRankerService.getTopComponentNames(topK); - } - return mTargetRanks.entrySet().stream() - .sorted(Entry.comparingByValue()) - .limit(topK) - .map(Entry::getKey) - .collect(Collectors.toList()); + return mComparatorModel.getScore(name); } @Override void updateModel(ComponentName componentName) { - if (mResolverRankerService != null) { - mResolverRankerService.updateModel(componentName); - return; - } - mAppPredictor.notifyAppTargetEvent( - new AppTargetEvent.Builder( - new AppTarget.Builder( - new AppTargetId(componentName.toString()), - componentName.getPackageName(), mUser) - .setClassName(componentName.getClassName()).build(), - ACTION_LAUNCH).build()); + mComparatorModel.notifyOnTargetSelected(componentName); } @Override @@ -220,6 +180,97 @@ class AppPredictionServiceResolverComparator extends AbstractResolverComparator if (mResolverRankerService != null) { mResolverRankerService.destroy(); mResolverRankerService = null; + mComparatorModel = buildUpdatedModel(); + } + } + + /** + * Re-construct an {@code AppPredictionServiceComparatorModel} to replace the current model + * instance (if any) using the up-to-date {@code AppPredictionServiceResolverComparator} 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 AppPredictionServiceComparatorModel} 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 AppPredictionServiceComparatorModel buildUpdatedModel() { + return new AppPredictionServiceComparatorModel( + mAppPredictor, mResolverRankerService, mUser, mTargetRanks); + } + + // 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 ResolverRankerServiceResolverComparator mResolverRankerService; + private final UserHandle mUser; + private final Map<ComponentName, Integer> mTargetRanks; // Treat as immutable. + + AppPredictionServiceComparatorModel( + AppPredictor appPredictor, + @Nullable ResolverRankerServiceResolverComparator resolverRankerService, + UserHandle user, + Map<ComponentName, Integer> targetRanks) { + mAppPredictor = appPredictor; + mResolverRankerService = resolverRankerService; + mUser = user; + mTargetRanks = targetRanks; + } + + @Override + public Comparator<ResolveInfo> getComparator() { + return (lhs, rhs) -> { + if (mResolverRankerService != null) { + return mResolverRankerService.compare(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; + }; + } + + @Override + public float getScore(ComponentName name) { + if (mResolverRankerService != null) { + return mResolverRankerService.getScore(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) { + if (mResolverRankerService != null) { + mResolverRankerService.updateModel(componentName); + return; + } + 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 d4a8a164803f..595c9634f8ba 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; @@ -2605,7 +2609,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/ChooserUtil.java b/core/java/com/android/internal/app/ChooserUtil.java deleted file mode 100644 index 3f8788cba9b9..000000000000 --- a/core/java/com/android/internal/app/ChooserUtil.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.app; - -import java.nio.charset.Charset; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -/** - * Utility method for common computation operations for Share sheet. - */ -public class ChooserUtil { - - private static final Charset UTF_8 = Charset.forName("UTF-8"); - - /** - * Hashes the given input based on MD5 algorithm. - * - * @return a string representation of the hash computation. - */ - public static String md5(String input) { - try { - MessageDigest md = MessageDigest.getInstance("MD5"); - md.update(input.getBytes(UTF_8)); - return convertBytesToHexString(md.digest()); - } catch (NoSuchAlgorithmException e) { - throw new IllegalStateException(e); - } - } - - /** Converts byte array input into an hex string. */ - private static String convertBytesToHexString(byte[] input) { - char[] chars = new char[input.length * 2]; - for (int i = 0; i < input.length; i++) { - byte b = input[i]; - chars[i * 2] = Character.forDigit((b >> 4) & 0xF, 16 /* radix */); - chars[i * 2 + 1] = Character.forDigit(b & 0xF, 16 /* radix */); - } - return new String(chars); - } - - private ChooserUtil() {} -} 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..988ecc78d408 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); } 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/app/SimpleIconFactory.java b/core/java/com/android/internal/app/SimpleIconFactory.java index 43dacd72db37..354eb62ba045 100644 --- a/core/java/com/android/internal/app/SimpleIconFactory.java +++ b/core/java/com/android/internal/app/SimpleIconFactory.java @@ -71,7 +71,7 @@ public class SimpleIconFactory { new SynchronizedPool<>(Runtime.getRuntime().availableProcessors()); private static final int DEFAULT_WRAPPER_BACKGROUND = Color.WHITE; - private static final float BLUR_FACTOR = 0.5f / 48; + private static final float BLUR_FACTOR = 1.5f / 48; private Context mContext; private Canvas mCanvas; @@ -650,8 +650,8 @@ public class SimpleIconFactory { /* Shadow generator block */ private static final float KEY_SHADOW_DISTANCE = 1f / 48; - private static final int KEY_SHADOW_ALPHA = 61; - private static final int AMBIENT_SHADOW_ALPHA = 30; + private static final int KEY_SHADOW_ALPHA = 10; + private static final int AMBIENT_SHADOW_ALPHA = 7; private Paint mBlurPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); private Paint mDrawPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); 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 f19bfc669997..daf2cf0504e9 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/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 518fc09dee5a..b301703158f6 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -2036,7 +2036,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/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 4075c5f4d8ae..fc7b634068f2 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" /> @@ -3735,12 +3736,6 @@ <permission android:name="android.permission.BIND_ATTESTATION_VERIFICATION_SERVICE" android:protectionLevel="signature" /> - <!-- Allows the caller to generate keymint keys with the INCLUDE_UNIQUE_ID tag, which - uniquely identifies the device via the attestation certificate. - @hide @TestApi --> - <permission android:name="android.permission.REQUEST_UNIQUE_ID_ATTESTATION" - android:protectionLevel="signature" /> - <!-- ========================================= --> <!-- Permissions for special development tools --> <!-- ========================================= --> @@ -4407,13 +4402,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/config.xml b/core/res/res/values/config.xml index 35bed2d76425..30fb45e3a6f1 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -3736,6 +3736,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 f177226c4ec3..61ca18c59813 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -393,6 +393,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/res/res/xml-watch/default_zen_mode_config.xml b/core/res/res/xml-watch/default_zen_mode_config.xml deleted file mode 100644 index 938cc0c3f7c0..000000000000 --- a/core/res/res/xml-watch/default_zen_mode_config.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright 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. ---> - -<!-- 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> 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/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java index e7a23f262753..43fba529182e 100644 --- a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java +++ b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java @@ -516,8 +516,6 @@ public class ResolverActivityTest { onView(withText(R.string.resolver_work_tab)) .perform(click()); waitForIdle(); - // wait for the share sheet to expand - Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS); onView(first(allOf(withText(workResolvedComponentInfos.get(0) .getResolveInfoAt(0).activityInfo.applicationInfo.name), isCompletelyDisplayed()))) .perform(click()); @@ -616,8 +614,6 @@ public class ResolverActivityTest { onView(withText(R.string.resolver_work_tab)) .perform(click()); waitForIdle(); - // wait for the share sheet to expand - Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS); onView(first(allOf( withText(workResolvedComponentInfos.get(0) .getResolveInfoAt(0).activityInfo.applicationInfo.name), 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/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..3a1107939c9f 100644 --- a/libs/WindowManager/Shell/res/values-de/strings.xml +++ b/libs/WindowManager/Shell/res/values-de/strings.xml @@ -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..9e7257112c6c 100644 --- a/libs/WindowManager/Shell/res/values-fa/strings.xml +++ b/libs/WindowManager/Shell/res/values-fa/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-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..dd5416f2e398 100644 --- a/libs/WindowManager/Shell/res/values-it/strings.xml +++ b/libs/WindowManager/Shell/res/values-it/strings.xml @@ -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/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/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/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/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/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/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/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..3f86dd5d000c 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="consent_back" msgid="2560683030046918882">"Terug"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-am/strings.xml b/packages/CompanionDeviceManager/res/values-am/strings.xml index 5cb306f14380..0c8504768e73 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="consent_back" msgid="2560683030046918882">"ተመለስ"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"የመተግበሪያ ፈቃዶችን ወደ የእጅ ሰዓትዎ ያስተላልፉ"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"የእጅ ሰዓትዎን ማቀናበርን ለማቅለል በማዋቀር ጊዜ በእጅ ሰዓትዎ ላይ የተጫኑ መተግበሪያዎች እንደ ስልክዎ ተመሳሳይ ፈቃዶችን ይጠቀማሉ።\n\n እነዚህ ፈቃዶች የእጅ ሰዓትዎ ማይክሮፎን እና አካባቢ መዳረሻን ሊያካትቱ ይችላሉ።"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-ar/strings.xml b/packages/CompanionDeviceManager/res/values-ar/strings.xml index b4c74ad07e40..4386e6a0314c 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="consent_back" msgid="2560683030046918882">"رجوع"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"نقل أذونات التطبيقات إلى ساعتك"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"لتسهيل إعداد ساعتك، فإن التطبيقات التي يتم تثبيتها على ساعتك أثناء الإعداد ستستخدم الأذونات نفسها التي يستخدمها هاتفك.\n\n قد تشتمل هذه الأذونات على الوصول إلى ميكروفون ساعتك وبيانات موقعها الجغرافي."</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-as/strings.xml b/packages/CompanionDeviceManager/res/values-as/strings.xml index b2865dc79ad5..b099d0cb4ef9 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="consent_back" msgid="2560683030046918882">"উভতি যাওক"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"আপোনাৰ ঘড়ীলৈ এপৰ অনুমতিসমূহ স্থানান্তৰ কৰক"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"আপোনাৰ ঘড়ীটো ছেটআপ কৰাটো অধিক সহজ কৰি তুলিবলৈ, এয়া কৰাৰ সময়ত আপোনাৰ ঘড়ীটোত ইনষ্টল কৰি থোৱা এপ্সমূহে আপোনাৰ ফ’নৰ দৰে একেই অনুমতিসমূহ ব্যৱহাৰ কৰিব।\n\n এই অনুমতিসমূহত আপোনাৰ ঘড়ীৰ মাইক্ৰ’ফ’ন আৰু অৱস্থানৰ এক্সেছ অন্তৰ্ভুক্ত হ’ব পাৰে।"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-az/strings.xml b/packages/CompanionDeviceManager/res/values-az/strings.xml index e8e4e7631481..1166ca1f4678 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="consent_back" msgid="2560683030046918882">"Geriyə"</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> </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..9123e05d912f 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="consent_back" msgid="2560683030046918882">"Nazad"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-be/strings.xml b/packages/CompanionDeviceManager/res/values-be/strings.xml index 3a57bcc34fb6..32264b431f0c 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="consent_back" msgid="2560683030046918882">"Назад"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Перанос дазволаў праграм на ваш гадзіннік"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"Для праграм, усталяваных на гадзіннік падчас наладжвання, будуць дзейнічаць тыя самыя дазволы, што і на тэлефоне.\n\n Так гадзіннік можа атрымаць доступ да мікрафона і даных пра месцазнаходжанне."</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-bg/strings.xml b/packages/CompanionDeviceManager/res/values-bg/strings.xml index d29a9081afc0..b603cb2b638a 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="consent_back" msgid="2560683030046918882">"Назад"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Прехвърляне на разрешенията за приложенията към часовника"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"За по-лесно конфигуриране на часовника ви приложенията, инсталирани на него по време на настройването, ще използват същите разрешения като предоставените на телефона ви.\n\nТе може да включват достъп до микрофона и местоположението на часовника ви."</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-bn/strings.xml b/packages/CompanionDeviceManager/res/values-bn/strings.xml index 7d0b097f2a99..498ea9a10b9d 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="consent_back" msgid="2560683030046918882">"ফিরুন"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"অ্যাপকে দেওয়া অনুমতি আপনার ঘড়িতে ট্রান্সফার করুন"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"ঘড়ি আরও সহজে সেট আপ করতে, সেট আপ চলাকালীন আপনার ঘড়িতে ইনস্টল করা অ্যাপ ফোনের মতো একই অনুমতি ব্যবহার করবে।\n\n এইসব অনুমতির মধ্যে আপনার ঘড়ির মাইক্রোফোন ও লোকেশন সম্পর্কে তথ্যের অ্যাক্সেস অন্তর্ভুক্ত থাকতে পারে।"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-bs/strings.xml b/packages/CompanionDeviceManager/res/values-bs/strings.xml index a723da8f59a4..dc7efa0a3650 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="consent_back" msgid="2560683030046918882">"Nazad"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-ca/strings.xml b/packages/CompanionDeviceManager/res/values-ca/strings.xml index de7e2256ede8..34fc76a6cf63 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="consent_back" msgid="2560683030046918882">"Enrere"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-cs/strings.xml b/packages/CompanionDeviceManager/res/values-cs/strings.xml index f195e54f743c..e8c7b0983d54 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="consent_back" msgid="2560683030046918882">"Zpět"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-da/strings.xml b/packages/CompanionDeviceManager/res/values-da/strings.xml index a2aa5dddb43c..df413002ee68 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="consent_back" msgid="2560683030046918882">"Tilbage"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-de/strings.xml b/packages/CompanionDeviceManager/res/values-de/strings.xml index 2b5ab117900e..6134390ad5ba 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="consent_back" msgid="2560683030046918882">"Zurück"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-el/strings.xml b/packages/CompanionDeviceManager/res/values-el/strings.xml index 339f85a58127..4713c5d6948d 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="consent_back" msgid="2560683030046918882">"Πίσω"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Μεταφορά αδειών εφαρμογών στο ρολόι σας"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"Για να είναι πιο εύκολη η ρύθμιση του ρολογιού σας, οι εφαρμογές που εγκαθίστανται στο ρολόι σας κατά τη ρύθμιση, θα χρησιμοποιούν τις ίδιες άδειες με το τηλέφωνό σας.\n\n Στις άδειες ενδέχεται να περιλαμβάνεται άδεια πρόσβασης στο μικρόφωνο και την τοποθεσία του ρολογιού σας."</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml b/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml index d59641111959..fff1e5e64a05 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="consent_back" msgid="2560683030046918882">"Back"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml b/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml index d59641111959..fff1e5e64a05 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="consent_back" msgid="2560683030046918882">"Back"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml b/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml index d59641111959..fff1e5e64a05 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="consent_back" msgid="2560683030046918882">"Back"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml b/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml index d59641111959..fff1e5e64a05 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="consent_back" msgid="2560683030046918882">"Back"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml b/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml index 9f17a89099d6..a9a9631d6157 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="consent_back" msgid="2560683030046918882">"Back"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml index 5423d3eeff87..60b136ae1bf2 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="consent_back" msgid="2560683030046918882">"Atrás"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-es/strings.xml b/packages/CompanionDeviceManager/res/values-es/strings.xml index ccbdd250dad2..bcf6621ed5b6 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="consent_back" msgid="2560683030046918882">"Atrás"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-et/strings.xml b/packages/CompanionDeviceManager/res/values-et/strings.xml index d8f1e9920736..49483ec46a54 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="consent_back" msgid="2560683030046918882">"Tagasi"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-eu/strings.xml b/packages/CompanionDeviceManager/res/values-eu/strings.xml index de768249916c..ec0ac2001449 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="consent_back" msgid="2560683030046918882">"Atzera"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-fa/strings.xml b/packages/CompanionDeviceManager/res/values-fa/strings.xml index 65ed2dde864f..663d7c5d9cc5 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="consent_back" msgid="2560683030046918882">"برگشت"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"انتقال اجازههای برنامه به ساعت"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"برای آسانتر کردن راهاندازی ساعت، برنامههای نصبشده در ساعت درحین راهاندازی از همان اجازههای تلفن استفاده خواهند کرد.\n\n ممکن است این اجازهها شامل دسترسی به میکروفون و مکان ساعت باشد."</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-fi/strings.xml b/packages/CompanionDeviceManager/res/values-fi/strings.xml index c8dbeb54402a..b10dc6951e98 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="consent_back" msgid="2560683030046918882">"Takaisin"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml b/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml index 3d5898b0a5a9..8d2b99e95696 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="consent_back" msgid="2560683030046918882">"Retour"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-fr/strings.xml b/packages/CompanionDeviceManager/res/values-fr/strings.xml index ecd89aa97ec9..e6167cd8e2fb 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="consent_back" msgid="2560683030046918882">"Retour"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-gl/strings.xml b/packages/CompanionDeviceManager/res/values-gl/strings.xml index d060f29a7e02..3a948630ea34 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="consent_back" msgid="2560683030046918882">"Atrás"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-gu/strings.xml b/packages/CompanionDeviceManager/res/values-gu/strings.xml index d06d8c677fd4..6012c6c91a9f 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="consent_back" msgid="2560683030046918882">"પાછળ"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"તમારી ઘડિયાળમાં ઍપ પરવાનગીઓ ટ્રાન્સફર કરો"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"તમારી ઘડિયાળનું સેટઅપ કરવાનું સરળ બનાવવા માટે, સેટઅપ દરમિયાન તમારી ઘડિયાળ પર ઇન્સ્ટૉલ કરેલી ઍપ દ્વારા તમારા ફોન પર મળેલી પરવાનગીઓનો ઉપયોગ કરવામાં આવશે.\n\n આ પરવાનગીઓમાં તમારી ઘડિયાળના માઇક્રોફોન અને સ્થાન સંબંધિત માહિતીનો ઍક્સેસ શામેલ હોઈ શકે છે."</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-hi/strings.xml b/packages/CompanionDeviceManager/res/values-hi/strings.xml index 1be6af8af0ec..aa0628ebb734 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="consent_back" msgid="2560683030046918882">"वापस जाएं"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"ऐप्लिकेशन से जुड़ी अनुमतियों को अपनी वॉच में ट्रांसफ़र करें"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"वॉच को सेट अप करने की प्रोसेस को आसान बनाने के लिए, उस पर इंस्टॉल किए गए ऐप्लिकेशन को भी वही अनुमतियां मिलेंगी जो आपने उन ऐप्लिकेशन को फ़ोन पर दी होंगी.\n\n इन अनुमतियों में, आपकी वॉच के माइक्रोफ़ोन और जगह की जानकारी का ऐक्सेस शामिल हो सकता है."</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-hr/strings.xml b/packages/CompanionDeviceManager/res/values-hr/strings.xml index 610b7bdffa70..f5cd4281671c 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="consent_back" msgid="2560683030046918882">"Natrag"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-hu/strings.xml b/packages/CompanionDeviceManager/res/values-hu/strings.xml index 625a3e9cd4aa..1ea2de1ad792 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="consent_back" msgid="2560683030046918882">"Vissza"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-hy/strings.xml b/packages/CompanionDeviceManager/res/values-hy/strings.xml index f09441fcdb4c..592a6c33624f 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="consent_back" msgid="2560683030046918882">"Հետ"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Հավելվածների թույլտվությունների տեղափոխում ժամացույց"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"Կարգավորման ժամանակ ժամացույցում տեղադրված հավելվածների համար կօգտագործվեն նույն թույլտվությունները, ինչ հեռախոսում։\n\n Այդ թույլտվությունները կարող են ներառել ժամացույցի խոսափողի կամ տեղադրության տվյալների օգտագործումը։"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-in/strings.xml b/packages/CompanionDeviceManager/res/values-in/strings.xml index ef52808cd5ff..905f7c548f2c 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="consent_back" msgid="2560683030046918882">"Kembali"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-is/strings.xml b/packages/CompanionDeviceManager/res/values-is/strings.xml index c0ca2fcf3ba3..b389184cf9ae 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="consent_back" msgid="2560683030046918882">"Til baka"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-it/strings.xml b/packages/CompanionDeviceManager/res/values-it/strings.xml index 5f88b7a68432..ccf7e5557a51 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="consent_back" msgid="2560683030046918882">"Indietro"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-iw/strings.xml b/packages/CompanionDeviceManager/res/values-iw/strings.xml index 4a811f0aef9d..2f9c7e4f8bdb 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="consent_back" msgid="2560683030046918882">"חזרה"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"העברת ההרשאות הניתנות לאפליקציות אל השעון שלך"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"כדי לפשט את הגדרת השעון, אפליקציות שמותקנות במהלך ההגדרה יקבלו את אותן הרשאות שניתנו בטלפון.\n\n ההרשאות האלה עשויות לכלול גישה למיקרופון ולמיקום של השעון."</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-ja/strings.xml b/packages/CompanionDeviceManager/res/values-ja/strings.xml index 5e8d544d9b6a..7c887ffc66ab 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="consent_back" msgid="2560683030046918882">"戻る"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"スマートウォッチへのアプリの権限の移行"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"スマートウォッチのセットアップを簡単にするため、セットアップ時にスマートウォッチにインストールされたアプリに、スマートフォンと同じ権限が適用されます。\n\n これらの権限には、スマートウォッチのマイクや位置情報へのアクセス権も含まれることがあります。"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-ka/strings.xml b/packages/CompanionDeviceManager/res/values-ka/strings.xml index 3b179bf237dd..5b56c33441ae 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="consent_back" msgid="2560683030046918882">"უკან"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"აპის ნებართვების საათისთვის გადაცემა"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"საათის დაყენების გასამარტივებლად თქვენს საათში დაინსტალირებული აპები იმავე ნებართვებს გამოიყენებს, რასაც ტელეფონზე იყენებს.\n\n ეს ნებართვები, შესაძლოა, მოიცავდეს თქვენი საათის მიკროფონსა და მდებარეობაზე წვდომას."</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-kk/strings.xml b/packages/CompanionDeviceManager/res/values-kk/strings.xml index a7efb15ed0be..67d3e8e8786f 100644 --- a/packages/CompanionDeviceManager/res/values-kk/strings.xml +++ b/packages/CompanionDeviceManager/res/values-kk/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="consent_back" msgid="2560683030046918882">"Артқа"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Қолданба рұқсаттарын сағатқа ауыстыру"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"Реттеу кезінде сағатқа орнатылған қолданбалар телефондағыдай рұқсаттарды пайдаланады. Осылайша сағат оңай реттеледі.\n\n Бұл рұқсаттар сағаттың микрофоны мен геодерегін пайдалануды қамтиды."</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-km/strings.xml b/packages/CompanionDeviceManager/res/values-km/strings.xml index b18586316289..6c9c87475f18 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="consent_back" msgid="2560683030046918882">"ថយក្រោយ"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"ផ្ទេរការអនុញ្ញាតកម្មវិធីទៅនាឡិការបស់អ្នក"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"ដើម្បីជួយឱ្យការរៀបចំនាឡិការបស់អ្នកកាន់តែងាយស្រួល កម្មវិធីដែលបានដំឡើងនៅលើនាឡិការបស់អ្នកអំឡុងពេលរៀបចំនឹងប្រើការអនុញ្ញាតដូចគ្នានឹងទូរសព្ទរបស់អ្នកដែរ។\n\n ការអនុញ្ញាតទាំងនេះអាចរួមបញ្ចូលសិទ្ធិចូលប្រើទីតាំង និងមីក្រូហ្វូនរបស់នាឡិកាអ្នក។"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-kn/strings.xml b/packages/CompanionDeviceManager/res/values-kn/strings.xml index 64576ce8aec8..3c71300fad9c 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="consent_back" msgid="2560683030046918882">"ಹಿಂದೆ"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"ಆ್ಯಪ್ ಅನುಮತಿಗಳನ್ನು ನಿಮ್ಮ ವಾಚ್ಗೆ ವರ್ಗಾವಣೆ ಮಾಡಿ"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"ನಿಮ್ಮ ವಾಚ್ ಸೆಟಪ್ ಮಾಡುವುದನ್ನು ಸುಲಭವಾಗಿಸಲು, ಸೆಟಪ್ನ ಸಮಯದಲ್ಲಿ ನಿಮ್ಮ ವಾಚ್ನಲ್ಲಿ ಇನ್ಸ್ಟಾಲ್ ಮಾಡಿದ ಆ್ಯಪ್ಗಳು, ನಿಮ್ಮ ಫೋನ್ನಲ್ಲಿನ ಅನುಮತಿಗಳನ್ನೇ ಬಳಸಿಕೊಳ್ಳುತ್ತವೆ.\n\n ಈ ಅನುಮತಿಗಳು ನಿಮ್ಮ ವಾಚ್ನ ಮೈಕ್ರೊಫೋನ್ ಮತ್ತು ಸ್ಥಳದ ಪ್ರವೇಶವನ್ನು ಒಳಗೊಳ್ಳಬಹುದು."</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-ko/strings.xml b/packages/CompanionDeviceManager/res/values-ko/strings.xml index 5bf8eb4ae6ac..8a3ad35ff309 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="consent_back" msgid="2560683030046918882">"뒤"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"앱 권한을 시계로 이전"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"시계를 더 쉽게 설정하기 위해 설정하는 동안 시계에 설치된 앱에서 휴대전화와 동일한 권한을 사용합니다.\n\n 이러한 권한에는 시계의 마이크 및 위치 정보에 대한 액세스가 포함될 수 있습니다."</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-ky/strings.xml b/packages/CompanionDeviceManager/res/values-ky/strings.xml index 714dc9365bd6..51252975b45f 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="consent_back" msgid="2560683030046918882">"Артка"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Колдонмонун уруксаттарын саатка өткөрүү"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"Сааттын жөндөлүшүн жеңилдетүү үчүн жөндөө учурунда саатыңызга орнотулган колдонмолор телефонуңуздагы уруксаттарды колдонот.\n\n Мындай уруксаттарга саатыңыздын микрофонун же жайгашкан жерин колдонуу кириши мүмкүн."</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-lo/strings.xml b/packages/CompanionDeviceManager/res/values-lo/strings.xml index 95cab696240f..42400a0543e9 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="consent_back" msgid="2560683030046918882">"ກັບຄືນ"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"ໂອນຍ້າຍການອະນຸຍາດແອັບໄປຫາໂມງຂອງທ່ານ"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"ເພື່ອເຮັດໃຫ້ຕັ້ງຄ່າໂມງຂອງທ່ານໄດ້ງ່າຍຂຶ້ນ, ແອັບທີ່ຕິດຕັ້ງຢູ່ໂມງຂອງທ່ານໃນລະຫວ່າງການຕັ້ງຄ່າຈະໃຊ້ການອະນຸຍາດດຽວກັນກັບໂທລະສັບຂອງທ່ານ.\n\n ການອະນຸຍາດເຫຼົ່ານີ້ອາດຮວມສິດເຂົ້າເຖິງໄມໂຄຣໂຟນ ແລະ ສະຖານທີ່ຂອງທ່ານນຳ."</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-lt/strings.xml b/packages/CompanionDeviceManager/res/values-lt/strings.xml index 5d32fbbf9116..f79ea0767fd4 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="consent_back" msgid="2560683030046918882">"Atgal"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-lv/strings.xml b/packages/CompanionDeviceManager/res/values-lv/strings.xml index cabfc77bb27c..ce4f7ac9129a 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="consent_back" msgid="2560683030046918882">"Atpakaļ"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-mk/strings.xml b/packages/CompanionDeviceManager/res/values-mk/strings.xml index b4531b5c864e..7ea24e727a2a 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="consent_back" msgid="2560683030046918882">"Назад"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Префрлете ги дозволите за апликациите на вашиот часовник"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"За полесно поставувањето на часовникот, апликациите инсталирани на часовникот при поставувањето ќе ги користат истите дозволи како на телефонот.\n\n Овие дозволи може да опфаќаат пристап до микрофонот и локацијата на часовникот."</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-ml/strings.xml b/packages/CompanionDeviceManager/res/values-ml/strings.xml index 85952ca65fce..0de423ca4154 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="consent_back" msgid="2560683030046918882">"മടങ്ങുക"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"നിങ്ങളുടെ വാച്ചിലേക്ക് ആപ്പ് അനുമതികൾ കൈമാറുക"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"നിങ്ങളുടെ വാച്ച് സജ്ജീകരിക്കുന്നത് എളുപ്പമാക്കാൻ, സജ്ജീകരിക്കുമ്പോൾ ഫോണിലുള്ള അതേ അനുമതികൾ നിങ്ങളുടെ വാച്ചിൽ ഇൻസ്റ്റാൾ ചെയ്തിട്ടുള്ള ആപ്പുകൾ ഉപയോഗിക്കും.\n\n ഈ അനുമതികളിൽ നിങ്ങളുടെ വാച്ചിന്റെ മൈക്രോഫോണിലേക്കും ലോക്കേഷനിലേക്കുമുള്ള ആക്സസ് ഉൾപ്പെട്ടേക്കാം."</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-mn/strings.xml b/packages/CompanionDeviceManager/res/values-mn/strings.xml index c0d589d0aca7..f4dd0e1e3f21 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="consent_back" msgid="2560683030046918882">"Буцах"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Цагандаа аппын зөвшөөрлийг шилжүүлэх"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"Таны цагийг тохируулахад илүү хялбар болгохын тулд тохируулгын үеэр таны цаган дээр суулгасан аппууд нь утастай тань ижил зөвшөөрлийг ашиглана.\n\n Эдгээр зөвшөөрөлд таны цагийн микрофон болон байршлын хандалт зэрэг багтаж магадгүй."</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-mr/strings.xml b/packages/CompanionDeviceManager/res/values-mr/strings.xml index 0ce6ab712eb0..30e6820d9712 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="consent_back" msgid="2560683030046918882">"मागे जा"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"अॅप परवानग्या तुमच्या वॉचवर ट्रान्सफर करा"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"तुमचे वॉच सेट करणे आणखी सोपे करण्यासाठी, सेटअपदरम्यान तुमच्या वॉचवर इंस्टॉल केलेली ॲप्स ही तुमच्या फोनप्रमाणेच परवानग्या वापरतील.\n\n या परवानग्यांमध्ये तुमच्या वॉचचा मायक्रोफोन आणि स्थानाच्या अॅक्सेसचा समावेश असू शकतो."</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-ms/strings.xml b/packages/CompanionDeviceManager/res/values-ms/strings.xml index 2ca812889342..a0b561a5ec27 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="consent_back" msgid="2560683030046918882">"Kembali"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-my/strings.xml b/packages/CompanionDeviceManager/res/values-my/strings.xml index 1fb20bf2449e..31663e34d927 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="consent_back" msgid="2560683030046918882">"နောက်သို့"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"သင်၏နာရီသို့ အက်ပ်ခွင့်ပြုချက်များ လွှဲပြောင်းရန်"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"သင်၏နာရီ စနစ်ထည့်သွင်းရာတွင် ပိုလွယ်ကူစေရန် စနစ်ထည့်သွင်းနေစဉ်အတွင်း နာရီတွင်ထည့်သွင်းသော အက်ပ်များသည် သင့်ဖုန်းနှင့် အလားတူခွင့်ပြုချက်များကို သုံးပါမည်။\n\n ဤခွင့်ပြုချက်များတွင် သင့်နာရီ၏ မိုက်ခရိုဖုန်းနှင့် တည်နေရာတို့ကို သုံးခွင့် ပါဝင်နိုင်သည်။"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-nb/strings.xml b/packages/CompanionDeviceManager/res/values-nb/strings.xml index aa73f5dff065..3f4db79064f3 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="consent_back" msgid="2560683030046918882">"Tilbake"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-ne/strings.xml b/packages/CompanionDeviceManager/res/values-ne/strings.xml index 3ba75eb31aad..b13741e4340c 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="consent_back" msgid="2560683030046918882">"पछाडि"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"एपलाई दिइएका अनुमति घडीमा ट्रान्स्फर गर्नुहोस्"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"तपाईंको घडी सेटअप गर्ने कार्य सजिलो बनाउनका लागि सेटअप गर्ने क्रममा तपाईंको घडीमा इन्स्टल गरिएका एपहरूले पनि तपाईंको फोनमा दिइएको जस्तै अनुमति प्रयोग गर्ने छन्।\n\n यी अनुमतिमा तपाईंको घडीको माइक्रोफोन र लोकेसन प्रयोग गर्ने जस्ता अनुमति पर्न सक्छन्।"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-nl/strings.xml b/packages/CompanionDeviceManager/res/values-nl/strings.xml index bc09a58afee1..4001c811d9a9 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="consent_back" msgid="2560683030046918882">"Terug"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-or/strings.xml b/packages/CompanionDeviceManager/res/values-or/strings.xml index 92d0a5ef5f1d..888f6e3864a9 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="consent_back" msgid="2560683030046918882">"ପଛକୁ ଫେରନ୍ତୁ"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"ଆପଣଙ୍କ ୱାଚକୁ ଆପ ଅନୁମତିଗୁଡ଼ିକ ଟ୍ରାନ୍ସଫର କରନ୍ତୁ"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"ଆପଣଙ୍କ ୱାଚ ସେଟ ଅପ କରିବାକୁ ସହଜ କରିବା ପାଇଁ, ସେଟଅପ ସମୟରେ ଆପଣଙ୍କର ୱାଚରେ ଇନଷ୍ଟଲ କରାଯାଇଥିବା ଆପଗୁଡ଼ିକ ଆପଣଙ୍କ ଫୋନରେ ଥିବା ଆପଗୁଡ଼ିକ ପରି ସମାନ ଅନୁମତିଗୁଡ଼ିକ ବ୍ୟବହାର କରିବ।\n\n ଏହି ଅନୁମତିଗୁଡ଼ିକରେ ଆପଣଙ୍କ ୱାଚର ମାଇକ୍ରୋଫୋନ ଏବଂ ଲୋକେସନକୁ ଆକ୍ସେସ ଅନ୍ତର୍ଭୁକ୍ତ ହୋଇପାରେ।"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-pa/strings.xml b/packages/CompanionDeviceManager/res/values-pa/strings.xml index c28be2543707..8f16c54ec1cd 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="consent_back" msgid="2560683030046918882">"ਪਿੱਛੇ"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"ਐਪ ਇਜਾਜ਼ਤਾਂ ਨੂੰ ਆਪਣੀ ਘੜੀ \'ਤੇ ਟ੍ਰਾਂਸਫ਼ਰ ਕਰੋ"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"ਤੁਹਾਡੀ ਘੜੀ ਦਾ ਸੈੱਟਅੱਪ ਕਰਨਾ ਆਸਾਨ ਬਣਾਉਣ ਲਈ, ਤੁਹਾਡੀ ਘੜੀ \'ਤੇ ਸਥਾਪਤ ਐਪਾਂ ਸੈੱਟਅੱਪ ਦੌਰਾਨ ਉਹੀ ਇਜਾਜ਼ਤਾਂ ਵਰਤਣਗੀਆਂ ਜੋ ਤੁਹਾਡਾ ਫ਼ੋਨ ਵਰਤਦਾ ਹੈ।\n\n ਇਨ੍ਹਾਂ ਇਜਾਜ਼ਤਾਂ ਵਿੱਚ ਤੁਹਾਡੀ ਘੜੀ ਦੇ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਅਤੇ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚ ਸ਼ਾਮਲ ਹੋ ਸਕਦੀ ਹੈ।"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-pl/strings.xml b/packages/CompanionDeviceManager/res/values-pl/strings.xml index f9fd206250d9..840323854852 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="consent_back" msgid="2560683030046918882">"Wstecz"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml b/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml index 161188c70c6c..7f081f0c9f4d 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="consent_back" msgid="2560683030046918882">"Voltar"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml b/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml index 9124a405198a..6b0ac35c9ff7 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="consent_back" msgid="2560683030046918882">"Voltar"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-pt/strings.xml b/packages/CompanionDeviceManager/res/values-pt/strings.xml index 161188c70c6c..7f081f0c9f4d 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="consent_back" msgid="2560683030046918882">"Voltar"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-ro/strings.xml b/packages/CompanionDeviceManager/res/values-ro/strings.xml index da7ae9e0f1bd..2cfbdbbc885e 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="consent_back" msgid="2560683030046918882">"Înapoi"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-ru/strings.xml b/packages/CompanionDeviceManager/res/values-ru/strings.xml index dbb09c9e7c96..2b24fa212bf7 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="consent_back" msgid="2560683030046918882">"Назад"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Перенос разрешений для приложений на часы"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"Для приложений, установленных на часы во время настройки, будут использоваться те же разрешения, что и на телефоне.\n\n Например, может быть включен доступ к микрофону на часах или сведениям о местоположении."</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-si/strings.xml b/packages/CompanionDeviceManager/res/values-si/strings.xml index a3de2a393181..94078a49db86 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="consent_back" msgid="2560683030046918882">"ආපසු"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"ඔබගේ ඔරලෝසුවට යෙදුම් අවසර මාරු කිරීම"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"ඔබගේ ඔරලෝසුව පිහිටුවීම පහසු කිරීමට, පිහිටුවීමේදී ඔබගේ ඔරලෝසුවේ ස්ථාපනය කර ඇති යෙදුම් ඔබගේ දුරකථනයට සමාන අවසර භාවිත කරනු ඇත.\n\n මෙම අවසරවලට ඔබගේ ඔරලෝසුවේ මයික්රෆෝනයට සහ ස්ථානයට ප්රවේශය ඇතුළත් විය හැකිය."</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-sk/strings.xml b/packages/CompanionDeviceManager/res/values-sk/strings.xml index dd75ef590913..9a5c87ea6ac9 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="consent_back" msgid="2560683030046918882">"Späť"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-sl/strings.xml b/packages/CompanionDeviceManager/res/values-sl/strings.xml index 7cb5fb58fb60..e28ba2f6ead7 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="consent_back" msgid="2560683030046918882">"Nazaj"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-sq/strings.xml b/packages/CompanionDeviceManager/res/values-sq/strings.xml index 62c711abf398..ba13505e1438 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="consent_back" msgid="2560683030046918882">"Pas"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-sr/strings.xml b/packages/CompanionDeviceManager/res/values-sr/strings.xml index 8d51c62fd3e7..3be67ff2837c 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="consent_back" msgid="2560683030046918882">"Назад"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Пренесите дозволе за апликације на сат"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"Да бисмо поједноставили подешавање сата, апликације инсталиране на сату током подешавања ће користити исте дозволе као телефон.\n\n Те дозволе могу да обухватају приступ микрофону и локацији сата."</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-sv/strings.xml b/packages/CompanionDeviceManager/res/values-sv/strings.xml index ca1ec8769675..19a245658727 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="consent_back" msgid="2560683030046918882">"Tillbaka"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-sw/strings.xml b/packages/CompanionDeviceManager/res/values-sw/strings.xml index cf9260087bd2..68a15348b506 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="consent_back" msgid="2560683030046918882">"Nyuma"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-ta/strings.xml b/packages/CompanionDeviceManager/res/values-ta/strings.xml index b86ea1cffacf..c3c7eece58a3 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="consent_back" msgid="2560683030046918882">"பின்செல்"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"ஆப்ஸ் அனுமதிகளை உங்கள் வாட்ச்சிற்கு மாற்றுதல்"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"உங்கள் வாட்ச் அமைவை எளிதாக்க, உங்கள் மொபைலில் வழங்கியுள்ள அனுமதிகளையே அமைவின்போது வாட்ச்சில் நிறுவப்பட்ட ஆப்ஸும் பயன்படுத்தும்.\n\n உங்கள் வாட்ச்சிலுள்ள மைக்ரோஃபோன், இருப்பிடம் ஆகியவற்றுக்கான அணுகலும் இந்த அனுமதிகளில் அடங்கக்கூடும்."</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-te/strings.xml b/packages/CompanionDeviceManager/res/values-te/strings.xml index 73cf3e88e180..ec3289dec687 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="consent_back" msgid="2560683030046918882">"వెనుకకు"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"మీ వాచ్కు యాప్ అనుమతులను బదిలీ చేయండి"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"మీ వాచ్ను సెటప్ చేయడాన్ని సులభతరం చేయడానికి, సెటప్ సమయంలో మీ వాచ్లో ఇన్స్టాల్ చేయబడిన యాప్లు మీ ఫోన్లో యాప్లకు ఉన్న అవే అనుమతులను ఉపయోగిస్తాయి.\n\n ఈ అనుమతులతో మీ వాచ్ మైక్రోఫోన్, అలాగే లొకేషన్ కూడా ఉండవచ్చు."</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-th/strings.xml b/packages/CompanionDeviceManager/res/values-th/strings.xml index 6f29346debc5..2b4742612858 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="consent_back" msgid="2560683030046918882">"กลับ"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"โอนสิทธิ์ของแอปไปยังนาฬิกา"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"แอปที่ติดตั้งในนาฬิการะหว่างการตั้งค่าจะใช้สิทธิ์เดียวกันกับโทรศัพท์เพื่อให้การตั้งค่านาฬิกาง่ายขึ้น\n\n สิทธิ์เหล่านี้อาจรวมการเข้าถึงไมโครโฟนและตำแหน่งของนาฬิกา"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-tl/strings.xml b/packages/CompanionDeviceManager/res/values-tl/strings.xml index e557a385dd98..15953a6065c4 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="consent_back" msgid="2560683030046918882">"Bumalik"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-tr/strings.xml b/packages/CompanionDeviceManager/res/values-tr/strings.xml index c75214bf957e..8e0938ba004a 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="consent_back" msgid="2560683030046918882">"Geri"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-uk/strings.xml b/packages/CompanionDeviceManager/res/values-uk/strings.xml index 46a25b2ba185..3638058d2707 100644 --- a/packages/CompanionDeviceManager/res/values-uk/strings.xml +++ b/packages/CompanionDeviceManager/res/values-uk/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="consent_back" msgid="2560683030046918882">"Назад"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Перенести дозволи для додатків на годинник"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"Задля зручності додатки, установлені на годиннику протягом налаштування, використовуватимуть ті самі дозволи, що й на телефоні.\n\n До таких дозволів може належати доступ до мікрофона й геоданих годинника."</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-ur/strings.xml b/packages/CompanionDeviceManager/res/values-ur/strings.xml index c9f930f0f54b..a9512097985d 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="consent_back" msgid="2560683030046918882">"پیچھے"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"اپنی گھڑی پر ایپ کی اجازتیں منتقل کریں"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"آپ کی گھڑی کو سیٹ اپ کرنے کے عمل کو زیادہ آسان بنانے کے لیے، سیٹ اپ کے دوران آپ کی گھڑی پر انسٹال کردہ ایپس انہیں اجازتوں کا استعمال کریں گی جن کا استعمال آپ کا فون کرتا ہے۔\n\n ان اجازتوں میں آپ کی گھڑی کے مائیکروفون اور مقام تک کی رسائی شامل ہو سکتی ہے۔"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-uz/strings.xml b/packages/CompanionDeviceManager/res/values-uz/strings.xml index 91fdd946edf2..455f9efce52f 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="consent_back" msgid="2560683030046918882">"Orqaga"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-vi/strings.xml b/packages/CompanionDeviceManager/res/values-vi/strings.xml index 4f96bd4d7f1a..0cc362b8d49e 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="consent_back" msgid="2560683030046918882">"Quay lại"</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> </resources> diff --git a/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml index 3fdccf229bf8..5286d75eb983 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="consent_back" msgid="2560683030046918882">"返回"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"将应用权限转让给手表"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"为了让您更轻松地设置手表,在设置过程中安装在手表上的应用将使用与手机相同的权限。\n\n这些权限可能包括使用手表的麦克风和位置信息。"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml index a4dc0c9b6c81..1e6f515e17f5 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="consent_back" msgid="2560683030046918882">"返回"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"將應用程式權限轉移至手錶"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"為簡化手錶的設定程序,在設定過程中安裝到手錶上的應用程式都將沿用手機上的權限。\n\n這些權限可能包括手錶麥克風和位置的存取權。"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml index eec042429ca8..9cb91d0f1ef7 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="consent_back" msgid="2560683030046918882">"返回"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"將應用程式權限轉移到手錶上"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"為簡化手錶的設定程序,只要是在設定過程中安裝到手錶上的應用程式,都將沿用手機上的權限。\n\n 這些權限可能包括手錶的麥克風和位置資訊存取權。"</string> </resources> diff --git a/packages/CompanionDeviceManager/res/values-zu/strings.xml b/packages/CompanionDeviceManager/res/values-zu/strings.xml index be5a195fa5f7..a86eec2b085d 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="consent_back" msgid="2560683030046918882">"Emuva"</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> </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/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/backup/SystemSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java index 716ee845bea6..a6bfc408be7e 100644 --- a/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java +++ b/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java @@ -43,7 +43,6 @@ public class SystemSettings { Settings.System.FONT_SCALE, Settings.System.DIM_SCREEN, Settings.System.SCREEN_OFF_TIMEOUT, - Settings.System.SCREEN_OFF_TIMEOUT_DOCKED, Settings.System.SCREEN_BRIGHTNESS_MODE, Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, Settings.System.SCREEN_BRIGHTNESS_FOR_VR, diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java index bbfab0bfa792..84b018b8d7b6 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java @@ -315,6 +315,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/android/provider/settings/validators/SystemSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java index d4302963f2d3..06712cc68b89 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java @@ -111,7 +111,6 @@ public class SystemSettingsValidators { }); VALIDATORS.put(System.DISPLAY_COLOR_MODE_VENDOR_HINT, ANY_STRING_VALIDATOR); VALIDATORS.put(System.SCREEN_OFF_TIMEOUT, NON_NEGATIVE_INTEGER_VALIDATOR); - VALIDATORS.put(System.SCREEN_OFF_TIMEOUT_DOCKED, NON_NEGATIVE_INTEGER_VALIDATOR); VALIDATORS.put(System.SCREEN_BRIGHTNESS_FOR_VR, new InclusiveIntegerRangeValidator(0, 255)); VALIDATORS.put(System.SCREEN_BRIGHTNESS_MODE, BOOLEAN_VALIDATOR); VALIDATORS.put(System.ADAPTIVE_SLEEP, 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 e358b16d6ed4..4cdbba7e292b 100644 --- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java @@ -421,6 +421,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 a28c4cf6b0d4..1d101ee30284 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -683,8 +683,8 @@ <!-- 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" /> <application android:label="@string/app_label" android:theme="@android:style/Theme.DeviceDefault.DayNight" 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..2dba48cf155d --- /dev/null +++ b/packages/SystemUI/res-keyguard/drawable/qs_bluetooth_icon_off.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_on.xml b/packages/SystemUI/res-keyguard/drawable/qs_bluetooth_icon_on.xml new file mode 100644 index 000000000000..17a76116db25 --- /dev/null +++ b/packages/SystemUI/res-keyguard/drawable/qs_bluetooth_icon_on.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_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/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 d39b0d53c743..eeb37c7b062d 100644 --- a/packages/SystemUI/res/layout/media_output_list_item.xml +++ b/packages/SystemUI/res/layout/media_output_list_item.xml @@ -33,7 +33,7 @@ android:layout_height="match_parent" android:background="@drawable/media_output_item_background" android:layout_gravity="center_vertical|start"> - <com.android.systemui.media.dialog.MediaOutputSeekbar + <SeekBar android:id="@+id/volume_seekbar" android:splitTrack="false" android:visibility="gone" @@ -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"/> @@ -127,7 +127,6 @@ android:layout_gravity="right|center" android:button="@drawable/ic_circle_check_box" android:visibility="gone" - android:clickable="false" /> </FrameLayout> </LinearLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index 309a95f922d4..8007001004ef 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -836,7 +836,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 0cf2d1d52b20..c6762d3e0048 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -836,7 +836,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 cd1f6352cad6..932061e9b533 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -860,7 +860,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 12f133c3c8d3..316a45247f1b 100644 --- a/packages/SystemUI/res/values-as/strings.xml +++ b/packages/SystemUI/res/values-as/strings.xml @@ -836,7 +836,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 39524c610488..44f4117acd90 100644 --- a/packages/SystemUI/res/values-az/strings.xml +++ b/packages/SystemUI/res/values-az/strings.xml @@ -836,7 +836,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 e9839b980ac2..69c3c8a07336 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml @@ -842,7 +842,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 2c8ab6f90506..d3ef66043e3e 100644 --- a/packages/SystemUI/res/values-be/strings.xml +++ b/packages/SystemUI/res/values-be/strings.xml @@ -848,7 +848,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 376ed069b99b..5d0b2bba4383 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -836,7 +836,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 e48e5c432e7a..5e0c64f3a406 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/strings.xml @@ -836,7 +836,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> @@ -907,7 +906,7 @@ <string name="see_all_networks" msgid="3773666844913168122">"সবকটি দেখুন"</string> <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"নেটওয়ার্ক বদলাতে ইথারনেট ডিসকানেক্ট করুন"</string> <string name="wifi_scan_notify_message" msgid="3753839537448621794">"ডিভাইস সংক্রান্ত অভিজ্ঞতা আরও ভাল করতে, অ্যাপ ও পরিষেবা যেকোনও সময় আপনার ওয়াই-ফাই নেটওয়ার্ক স্ক্যান করতে পারবে, এমনকি ডিভাইসের ওয়াই-ফাই বন্ধ করা থাকলেও। ওয়াই-ফাই স্ক্যানিং সেটিংস থেকে আপনি এটি পরিবর্তন করতে পারবেন। "<annotation id="link">"পরিবর্তন করুন"</annotation></string> - <string name="turn_off_airplane_mode" msgid="8425587763226548579">"\'বিমান\' মোড বন্ধ করুন"</string> + <string name="turn_off_airplane_mode" msgid="8425587763226548579">"\'বিমান মোড\' বন্ধ করুন"</string> <string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> নিম্নলিখিত টাইল দ্রুত সেটিংস মেনুতে যোগ করতে চায়"</string> <string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"টাইল যোগ করুন"</string> <string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"টাইল যোগ করবেন না"</string> diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml index e692d3ca7777..bd2b4d0cad1f 100644 --- a/packages/SystemUI/res/values-bs/strings.xml +++ b/packages/SystemUI/res/values-bs/strings.xml @@ -839,7 +839,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 f8eb7b271ec1..ab7cba884f6d 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -836,7 +836,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 eec539fc7592..77761bee946b 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -848,7 +848,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 a1eb92a6a1ab..3636730b295b 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -836,7 +836,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 96d77bad9cc1..05956d90a34b 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -836,7 +836,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 319dca584e5f..b4af9474b039 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -836,7 +836,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 b3ab570b28e2..d42cc52f26c5 100644 --- a/packages/SystemUI/res/values-en-rAU/strings.xml +++ b/packages/SystemUI/res/values-en-rAU/strings.xml @@ -833,7 +833,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 6939dfc27d75..c5f7445a20be 100644 --- a/packages/SystemUI/res/values-en-rCA/strings.xml +++ b/packages/SystemUI/res/values-en-rCA/strings.xml @@ -833,7 +833,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 b3ab570b28e2..d42cc52f26c5 100644 --- a/packages/SystemUI/res/values-en-rGB/strings.xml +++ b/packages/SystemUI/res/values-en-rGB/strings.xml @@ -833,7 +833,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 b3ab570b28e2..d42cc52f26c5 100644 --- a/packages/SystemUI/res/values-en-rIN/strings.xml +++ b/packages/SystemUI/res/values-en-rIN/strings.xml @@ -833,7 +833,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 53cd65b1459d..601305b8fe42 100644 --- a/packages/SystemUI/res/values-en-rXC/strings.xml +++ b/packages/SystemUI/res/values-en-rXC/strings.xml @@ -833,7 +833,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 8fb5623b465c..416e097b7e2a 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -836,7 +836,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 e2f0b9bf24f8..35fbf2ab3247 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -836,7 +836,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 59e18e08be03..a06fd3a03e45 100644 --- a/packages/SystemUI/res/values-et/strings.xml +++ b/packages/SystemUI/res/values-et/strings.xml @@ -836,7 +836,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 feeef2d02ab9..a880334219ee 100644 --- a/packages/SystemUI/res/values-eu/strings.xml +++ b/packages/SystemUI/res/values-eu/strings.xml @@ -770,7 +770,7 @@ <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"kendu gogokoetatik"</string> <string name="accessibility_control_move" msgid="8980344493796647792">"Eraman <xliff:g id="NUMBER">%d</xliff:g>garren postura"</string> <string name="controls_favorite_default_title" msgid="967742178688938137">"Kontrolatzeko aukerak"</string> - <string name="controls_favorite_subtitle" msgid="6481675111056961083">"Aukeratu atzitu nahi dituzunak Ezarpen bizkorrak menutik"</string> + <string name="controls_favorite_subtitle" msgid="6481675111056961083">"Aukeratu Ezarpen bizkorrak menutik atzitu nahi dituzunak"</string> <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Kontrolatzeko aukerak antolatzeko, eduki itzazu sakatuta, eta arrastatu"</string> <string name="controls_favorite_removed" msgid="5276978408529217272">"Kendu dira kontrolatzeko aukera guztiak"</string> <string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Ez dira gorde aldaketak"</string> @@ -836,7 +836,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 c4255db3e2f2..13cccf0e1c7c 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -836,7 +836,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 f5b20a09e032..823c526f3fcb 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -836,7 +836,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 61eeb0c15936..f78773dfb41e 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -836,7 +836,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 17f1468f5e6f..1bdf0f279f85 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -836,7 +836,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 a3655f7f390e..78bbb28bb9fc 100644 --- a/packages/SystemUI/res/values-gl/strings.xml +++ b/packages/SystemUI/res/values-gl/strings.xml @@ -836,7 +836,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 614101147542..6085d763c94d 100644 --- a/packages/SystemUI/res/values-gu/strings.xml +++ b/packages/SystemUI/res/values-gu/strings.xml @@ -836,7 +836,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 17ee4427def6..49bafd4f2d8f 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -836,7 +836,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> @@ -850,7 +849,7 @@ <string name="select_conversation_title" msgid="6716364118095089519">"बातचीत विजेट"</string> <string name="select_conversation_text" msgid="3376048251434956013">"किसी बातचीत को होम स्क्रीन पर जोड़ने के लिए, उस बातचीत पर टैप करें"</string> <string name="no_conversations_text" msgid="5354115541282395015">"हाल ही में हुई बातचीत यहां दिखेंगी"</string> - <string name="priority_conversations" msgid="3967482288896653039">"प्राथमिकता वाली बातचीत"</string> + <string name="priority_conversations" msgid="3967482288896653039">"अहम बातचीत"</string> <string name="recent_conversations" msgid="8531874684782574622">"हाल ही में की गई बातचीत"</string> <string name="days_timestamp" msgid="5821854736213214331">"<xliff:g id="DURATION">%1$s</xliff:g> दिन पहले"</string> <string name="one_week_timestamp" msgid="4925600765473875590">"एक हफ़्ता पहले"</string> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index b9bf55380702..54b3912c4ac5 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -839,7 +839,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 4a8bca3facf8..3d2d01bcf7c4 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -836,7 +836,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 31dafac56cac..aa03db0a8887 100644 --- a/packages/SystemUI/res/values-hy/strings.xml +++ b/packages/SystemUI/res/values-hy/strings.xml @@ -836,7 +836,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 9bdca97beb36..396690f9d429 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -836,7 +836,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 2311a56e5264..251e4e2f6795 100644 --- a/packages/SystemUI/res/values-is/strings.xml +++ b/packages/SystemUI/res/values-is/strings.xml @@ -836,7 +836,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 029505da2d2b..84b1ffdc738c 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -836,7 +836,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 29e9c30b3598..bc2918d13771 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -848,7 +848,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 d136e688053f..5594fddc3196 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -135,8 +135,7 @@ <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"顔を認証しました"</string> <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"確認しました"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"完了するには [確認] をタップしてください"</string> - <!-- no translation found for biometric_dialog_tap_confirm_with_face (1092050545851021991) --> - <skip /> + <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"顔でロック解除しました。ロック解除アイコンを押して続行します。"</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> @@ -311,10 +310,8 @@ <string name="notification_tap_again" msgid="4477318164947497249">"開くにはもう一度タップしてください"</string> <string name="tap_again" msgid="1315420114387908655">"もう一度タップしてください"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"開くには上にスワイプします"</string> - <!-- no translation found for keyguard_unlock_press (9140109453735019209) --> - <skip /> - <!-- no translation found for keyguard_face_successful_unlock_press (25520941264602588) --> - <skip /> + <string name="keyguard_unlock_press" msgid="9140109453735019209">"ロック解除アイコンを押して開きます"</string> + <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"顔でロック解除しました。ロック解除アイコンを押して開きます。"</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> @@ -836,7 +833,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> @@ -913,11 +909,11 @@ <string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"タイルを追加しない"</string> <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"ユーザーの選択"</string> <plurals name="fgs_manager_footer_label" formatted="false" msgid="9091110396713032871"> - <item quantity="other">有効なアプリ: <xliff:g id="COUNT_1">%s</xliff:g> 個</item> - <item quantity="one">有効なアプリ: <xliff:g id="COUNT_0">%s</xliff:g> 個</item> + <item quantity="other">実行中のアプリ: <xliff:g id="COUNT_1">%s</xliff:g> 個</item> + <item quantity="one">実行中のアプリ: <xliff:g id="COUNT_0">%s</xliff:g> 個</item> </plurals> <string name="fgs_dot_content_description" msgid="2865071539464777240">"最新情報"</string> - <string name="fgs_manager_dialog_title" msgid="5879184257257718677">"有効なアプリ"</string> + <string name="fgs_manager_dialog_title" msgid="5879184257257718677">"実行中のアプリ"</string> <string name="fgs_manager_app_item_stop_button_label" msgid="7188317969020801156">"停止"</string> <string name="fgs_manager_app_item_stop_button_stopped_label" msgid="6950382004441263922">"停止中"</string> <string name="clipboard_edit_text_done" msgid="4551887727694022409">"完了"</string> diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml index c3c531e1a716..d7fb9feef690 100644 --- a/packages/SystemUI/res/values-ka/strings.xml +++ b/packages/SystemUI/res/values-ka/strings.xml @@ -135,8 +135,7 @@ <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"სახის ამოცნობილია"</string> <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"დადასტურებული"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"დასასრულებლად შეეხეთ „დადასტურებას“"</string> - <!-- no translation found for biometric_dialog_tap_confirm_with_face (1092050545851021991) --> - <skip /> + <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"განიბლოკა სახით. გასაგრძელებლად დააჭირეთ განბლოკვის ხატულას."</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> @@ -311,10 +310,8 @@ <string name="notification_tap_again" msgid="4477318164947497249">"შეეხეთ ისევ გასახსნელად"</string> <string name="tap_again" msgid="1315420114387908655">"შეეხეთ ხელახლა"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"გასახსნელად გადაფურცლეთ ზემოთ"</string> - <!-- no translation found for keyguard_unlock_press (9140109453735019209) --> - <skip /> - <!-- no translation found for keyguard_face_successful_unlock_press (25520941264602588) --> - <skip /> + <string name="keyguard_unlock_press" msgid="9140109453735019209">"გასახსნელად დააჭირეთ განბლოკვის ხატულას"</string> + <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"განიბლოკა სახით. გასახსნელად დააჭირეთ განბლოკვის ხატულას."</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> @@ -836,7 +833,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 be57f4614d38..05344864fdf0 100644 --- a/packages/SystemUI/res/values-kk/strings.xml +++ b/packages/SystemUI/res/values-kk/strings.xml @@ -836,7 +836,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 f7a02a949ab9..fc400e3c81d7 100644 --- a/packages/SystemUI/res/values-km/strings.xml +++ b/packages/SystemUI/res/values-km/strings.xml @@ -135,8 +135,7 @@ <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"បានផ្ទៀងផ្ទាត់មុខ"</string> <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"បានបញ្ជាក់"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ចុច \"បញ្ជាក់\" ដើម្បីបញ្ចប់"</string> - <!-- no translation found for biometric_dialog_tap_confirm_with_face (1092050545851021991) --> - <skip /> + <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"បានដោះសោដោយប្រើមុខ។ សូមចុចរូបដោះសោ ដើម្បីបន្ត។"</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> @@ -311,10 +310,8 @@ <string name="notification_tap_again" msgid="4477318164947497249">"ប៉ះម្ដងទៀត ដើម្បីបើក"</string> <string name="tap_again" msgid="1315420114387908655">"ចុចម្ដងទៀត"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"អូសឡើងលើដើម្បីបើក"</string> - <!-- no translation found for keyguard_unlock_press (9140109453735019209) --> - <skip /> - <!-- no translation found for keyguard_face_successful_unlock_press (25520941264602588) --> - <skip /> + <string name="keyguard_unlock_press" msgid="9140109453735019209">"ចុចរូបដោះសោ ដើម្បីបើក"</string> + <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"បានដោះសោដោយប្រើមុខ។ សូមចុចរូបដោះសោ ដើម្បីបើក។"</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> @@ -836,7 +833,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 00377995fdc3..865808adbf2d 100644 --- a/packages/SystemUI/res/values-kn/strings.xml +++ b/packages/SystemUI/res/values-kn/strings.xml @@ -836,7 +836,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 24bff1791a79..d52942a8e9b0 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -836,7 +836,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 552822c5f1de..a1b1c005f064 100644 --- a/packages/SystemUI/res/values-ky/strings.xml +++ b/packages/SystemUI/res/values-ky/strings.xml @@ -836,7 +836,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 8108efdf3b91..26840cb45aa5 100644 --- a/packages/SystemUI/res/values-lo/strings.xml +++ b/packages/SystemUI/res/values-lo/strings.xml @@ -836,7 +836,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 619d256dcb9b..c9bd89b9a67a 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -845,7 +845,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 62f06f72d2c4..e26e2baaf1e5 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -842,7 +842,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 195af88a21a0..34c742bfbb32 100644 --- a/packages/SystemUI/res/values-mk/strings.xml +++ b/packages/SystemUI/res/values-mk/strings.xml @@ -833,7 +833,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 4b4b098c4307..61b210187630 100644 --- a/packages/SystemUI/res/values-ml/strings.xml +++ b/packages/SystemUI/res/values-ml/strings.xml @@ -833,7 +833,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 27f55e993205..2627d6278048 100644 --- a/packages/SystemUI/res/values-mn/strings.xml +++ b/packages/SystemUI/res/values-mn/strings.xml @@ -135,8 +135,7 @@ <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Царайг баталгаажууллаа"</string> <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Баталгаажсан"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Дуусгахын тулд баталгаажуулахыг товших"</string> - <!-- no translation found for biometric_dialog_tap_confirm_with_face (1092050545851021991) --> - <skip /> + <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Царайгаар түгжээг тайлсан. Үргэлжлүүлэхийн тулд түгжээг тайлах дүрс тэмдэг дээр дараарай."</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> @@ -311,10 +310,8 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Нээхийн тулд дахин товшино уу"</string> <string name="tap_again" msgid="1315420114387908655">"Дaхин товшино уу"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Нээхийн тулд дээш шударна уу"</string> - <!-- no translation found for keyguard_unlock_press (9140109453735019209) --> - <skip /> - <!-- no translation found for keyguard_face_successful_unlock_press (25520941264602588) --> - <skip /> + <string name="keyguard_unlock_press" msgid="9140109453735019209">"Нээхийн тулд түгжээг тайлах дүрс тэмдэг дээр дараарай"</string> + <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Царайгаар түгжээг тайлсан. Нээхийн тулд түгжээг тайлах дүрс тэмдэг дээр дараарай."</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> @@ -836,7 +833,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 96ba72864f74..ffe91ba72b94 100644 --- a/packages/SystemUI/res/values-mr/strings.xml +++ b/packages/SystemUI/res/values-mr/strings.xml @@ -836,7 +836,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 0240e9cd7c00..d2596dce0eaa 100644 --- a/packages/SystemUI/res/values-ms/strings.xml +++ b/packages/SystemUI/res/values-ms/strings.xml @@ -836,7 +836,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 2ee78500344d..e795c452318b 100644 --- a/packages/SystemUI/res/values-my/strings.xml +++ b/packages/SystemUI/res/values-my/strings.xml @@ -836,7 +836,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 7b8115750601..7a3d90fe327b 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -836,7 +836,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 6338185969fe..8bb48acfec5d 100644 --- a/packages/SystemUI/res/values-ne/strings.xml +++ b/packages/SystemUI/res/values-ne/strings.xml @@ -698,7 +698,7 @@ <string name="mobile_data" msgid="4564407557775397216">"मोबाइल डेटा"</string> <string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string> <string name="mobile_carrier_text_format" msgid="8912204177152950766">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="MOBILE_DATA_TYPE">%2$s</xliff:g>"</string> - <string name="wifi_is_off" msgid="5389597396308001471">"Wi‑Fi निष्क्रिय छ"</string> + <string name="wifi_is_off" msgid="5389597396308001471">"Wi‑Fi अफ छ"</string> <string name="bt_is_off" msgid="7436344904889461591">"ब्लुटुथ निष्क्रिय छ"</string> <string name="dnd_is_off" msgid="3185706903793094463">"बाधा नपुर्याउनुहोस् नामक विकल्प निष्क्रिय छ"</string> <string name="qs_dnd_prompt_auto_rule" msgid="3535469468310002616">"कुनै स्वचालित नियमले बाधा नपुऱ्याउनुहोस् नामक विकल्पलाई सक्रियो गऱ्यो (<xliff:g id="ID_1">%s</xliff:g>)।"</string> @@ -717,7 +717,7 @@ <string name="slice_permission_allow" msgid="6340449521277951123">"अनुमति दिनुहोस्"</string> <string name="slice_permission_deny" msgid="6870256451658176895">"अस्वीकार गर्नु…"</string> <string name="auto_saver_title" msgid="6873691178754086596">"ब्याट्री सेभरको समयतालिका बनाउन ट्याप गर्नुहोस्"</string> - <string name="auto_saver_text" msgid="3214960308353838764">"ब्याट्री सकिने सम्भावना भएमा सक्रिय गर्नुहोस्"</string> + <string name="auto_saver_text" msgid="3214960308353838764">"ब्याट्री सकिने सम्भावना भएमा अन गर्नुहोस्"</string> <string name="no_auto_saver_action" msgid="7467924389609773835">"पर्दैन धन्यवाद"</string> <string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string> <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"एपहरूले तपाईंको <xliff:g id="TYPES_LIST">%s</xliff:g> प्रयोग गर्दै छन्।"</string> @@ -836,7 +836,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 3a638b1e5098..4b96d5d660ee 100644 --- a/packages/SystemUI/res/values-night/colors.xml +++ b/packages/SystemUI/res/values-night/colors.xml @@ -67,12 +67,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 acb194c667ea..d25f7d3b6ca1 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -836,7 +836,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 e5fb88c9ff2b..4395fb5b4bcc 100644 --- a/packages/SystemUI/res/values-or/strings.xml +++ b/packages/SystemUI/res/values-or/strings.xml @@ -836,7 +836,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 132de78ea96d..99c97d86b253 100644 --- a/packages/SystemUI/res/values-pa/strings.xml +++ b/packages/SystemUI/res/values-pa/strings.xml @@ -836,7 +836,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 2d560fa0c768..c1d86fc88991 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -848,7 +848,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 464414d6f8d7..696628e2f9af 100644 --- a/packages/SystemUI/res/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res/values-pt-rBR/strings.xml @@ -833,7 +833,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 d1124b66b8a6..044227756932 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -833,7 +833,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 464414d6f8d7..696628e2f9af 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -833,7 +833,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 d943d11d23e5..406fe664056d 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -842,7 +842,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 bf35e937a142..9a7367ac26b8 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -848,7 +848,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 1d0155343b84..b83fcae1bec6 100644 --- a/packages/SystemUI/res/values-si/strings.xml +++ b/packages/SystemUI/res/values-si/strings.xml @@ -836,7 +836,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 f45fc9d5ed1f..9abb7f6ebfe3 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -848,7 +848,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 134dba5ac2e6..1e645fb80931 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -848,7 +848,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 3e7cbb001068..f15048771bdd 100644 --- a/packages/SystemUI/res/values-sq/strings.xml +++ b/packages/SystemUI/res/values-sq/strings.xml @@ -836,7 +836,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 0991763c09dd..ffb5ab179a4a 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -842,7 +842,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 c6c9d119a173..3a016e655e01 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -836,7 +836,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 410a661cf5cf..64ab1fad243a 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -836,7 +836,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 3925dba8cb24..15f5bbc11aeb 100644 --- a/packages/SystemUI/res/values-ta/strings.xml +++ b/packages/SystemUI/res/values-ta/strings.xml @@ -351,7 +351,7 @@ <string name="user_remove_user_remove" msgid="8387386066949061256">"அகற்று"</string> <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> உங்கள் திரையில் தெரியும் தகவல்கள், ரெக்கார்டு செய்யும்போதோ அனுப்பும்போதோ உங்கள் சாதனத்திலிருந்து பிளே ஆகும் அனைத்து தகவல்கள் ஆகியவற்றுக்கான அணுகலைக் கொண்டிருக்கும். கடவுச்சொற்கள், பேமெண்ட் தொடர்பான தகவல்கள், படங்கள், மெசேஜ்கள், நீங்கள் பிளே செய்யும் ஆடியோ போன்ற அனைத்துத் தகவல்களும் இதில் அடங்கும்."</string> <string name="media_projection_dialog_service_text" msgid="958000992162214611">"இந்தச் செயல்பாட்டை வழங்கும் சேவையானது உங்கள் திரையில் தெரியும் தகவல்கள், ரெக்கார்டு செய்யும்போதோ அனுப்பும்போதோ உங்கள் சாதனத்திலிருந்து பிளே ஆகும் அனைத்துத் தகவல்கள் ஆகியவற்றுக்கான அணுகலைக் கொண்டிருக்கும். கடவுச்சொற்கள், பேமெண்ட் தொடர்பான தகவல்கள், படங்கள், மெசேஜ்கள், நீங்கள் பிளே செய்யும் ஆடியோ போன்ற அனைத்துத் தகவல்களும் இதில் அடங்கும்."</string> - <string name="media_projection_dialog_service_title" msgid="2888507074107884040">"ரெக்கார்டிங் செய்யவோ அனுப்புவதற்கோ தொடங்கிவிட்டீர்களா?"</string> + <string name="media_projection_dialog_service_title" msgid="2888507074107884040">"ரெக்கார்டிங் செய்யவோ அனுப்புவோ தொடங்கவா?"</string> <string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> மூலம் ரெக்கார்டிங் செய்யவோ அனுப்புவதற்கோ தொடங்கிவீட்டீர்களா?"</string> <string name="clear_all_notifications_text" msgid="348312370303046130">"எல்லாவற்றையும் அழி"</string> <string name="manage_notifications_text" msgid="6885645344647733116">"நிர்வகி"</string> @@ -836,7 +836,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> @@ -850,7 +849,7 @@ <string name="select_conversation_title" msgid="6716364118095089519">"உரையாடல் விட்ஜெட்டுகள்"</string> <string name="select_conversation_text" msgid="3376048251434956013">"ஓர் உரையாடலை உங்கள் முகப்புத் திரையில் சேர்க்க அந்த உரையாடலைத் தட்டுங்கள்"</string> <string name="no_conversations_text" msgid="5354115541282395015">"உங்கள் சமீபத்திய உரையாடல்கள் இங்கே காட்டப்படும்"</string> - <string name="priority_conversations" msgid="3967482288896653039">"முன்னுரிமை அளிக்கப்பட்ட உரையாடல்கள்"</string> + <string name="priority_conversations" msgid="3967482288896653039">"முக்கிய உரையாடல்கள்"</string> <string name="recent_conversations" msgid="8531874684782574622">"சமீபத்திய உரையாடல்கள்"</string> <string name="days_timestamp" msgid="5821854736213214331">"<xliff:g id="DURATION">%1$s</xliff:g> நாட்களுக்கு முன்பு"</string> <string name="one_week_timestamp" msgid="4925600765473875590">"1 வாரத்திற்கு முன்பு"</string> diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml index c0f45d33dd6e..8aea06186626 100644 --- a/packages/SystemUI/res/values-te/strings.xml +++ b/packages/SystemUI/res/values-te/strings.xml @@ -771,7 +771,7 @@ <string name="accessibility_control_move" msgid="8980344493796647792">"<xliff:g id="NUMBER">%d</xliff:g> పొజిషన్కు తరలించండి"</string> <string name="controls_favorite_default_title" msgid="967742178688938137">"నియంత్రణలు"</string> <string name="controls_favorite_subtitle" msgid="6481675111056961083">"త్వరిత సెట్టింగ్ల నుండి యాక్సెస్ చేయడానికి కంట్రోల్స్ను ఎంచుకోండి"</string> - <string name="controls_favorite_rearrange" msgid="5616952398043063519">"కంట్రోల్స్ క్రమం మార్చడానికి దేనినైనా పట్టుకుని, లాగి వదిలేయండి"</string> + <string name="controls_favorite_rearrange" msgid="5616952398043063519">"కంట్రోల్స్ క్రమం మార్చడానికి దేన్నయినా పట్టుకుని, లాగి వదలండి"</string> <string name="controls_favorite_removed" msgid="5276978408529217272">"అన్ని కంట్రోల్స్ తీసివేయబడ్డాయి"</string> <string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"మార్పులు సేవ్ చేయబడలేదు"</string> <string name="controls_favorite_see_other_apps" msgid="7709087332255283460">"ఇతర యాప్లను చూడండి"</string> @@ -836,7 +836,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 2ff5315ddebc..78e138d2267e 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -836,7 +836,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 9e6c15cc15da..9721b75b19ae 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -135,8 +135,7 @@ <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Na-authenticate ang mukha"</string> <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> - <!-- no translation found for biometric_dialog_tap_confirm_with_face (1092050545851021991) --> - <skip /> + <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_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> @@ -311,10 +310,8 @@ <string name="notification_tap_again" msgid="4477318164947497249">"I-tap ulit upang buksan"</string> <string name="tap_again" msgid="1315420114387908655">"I-tap ulit"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Mag-swipe pataas para buksan"</string> - <!-- no translation found for keyguard_unlock_press (9140109453735019209) --> - <skip /> - <!-- no translation found for keyguard_face_successful_unlock_press (25520941264602588) --> - <skip /> + <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_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> @@ -836,7 +833,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 00ce33d3e25c..dfbdcb9b04d1 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -836,7 +836,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 c5cf9fa073fd..5fb675905516 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -848,7 +848,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 55778f83b52e..bd9bb2fb54cb 100644 --- a/packages/SystemUI/res/values-ur/strings.xml +++ b/packages/SystemUI/res/values-ur/strings.xml @@ -836,7 +836,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 362208f47039..9b6295de96c1 100644 --- a/packages/SystemUI/res/values-uz/strings.xml +++ b/packages/SystemUI/res/values-uz/strings.xml @@ -836,7 +836,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 a2f9dd2f5da3..508fdb1f5f7f 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -836,7 +836,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 d8f445732f5b..fdee02f0a894 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -836,7 +836,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 82f458f69116..d20a9a027b75 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings.xml @@ -91,7 +91,7 @@ <string name="screenrecord_name" msgid="2596401223859996572">"螢幕畫面錄影工具"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"正在處理螢幕錄影內容"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"持續顯示錄影畫面工作階段通知"</string> - <string name="screenrecord_start_label" msgid="1750350278888217473">"要開始錄影嗎?"</string> + <string name="screenrecord_start_label" msgid="1750350278888217473">"要開始錄製嗎?"</string> <string name="screenrecord_description" msgid="1123231719680353736">"錄影時,Android 系統可擷取螢幕上顯示或裝置播放的任何敏感資料,包括密碼、付款資料、相片、訊息和音訊。"</string> <string name="screenrecord_audio_label" msgid="6183558856175159629">"錄音"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"裝置音訊"</string> @@ -135,8 +135,7 @@ <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"臉孔已經驗證"</string> <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"已確認"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"輕按 [確定] 以完成"</string> - <!-- no translation found for biometric_dialog_tap_confirm_with_face (1092050545851021991) --> - <skip /> + <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"已使用面孔解鎖。按解鎖圖示即可繼續。"</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> @@ -311,10 +310,8 @@ <string name="notification_tap_again" msgid="4477318164947497249">"再次輕按即可開啟"</string> <string name="tap_again" msgid="1315420114387908655">"再次輕按"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"向上滑動即可開啟"</string> - <!-- no translation found for keyguard_unlock_press (9140109453735019209) --> - <skip /> - <!-- no translation found for keyguard_face_successful_unlock_press (25520941264602588) --> - <skip /> + <string name="keyguard_unlock_press" msgid="9140109453735019209">"按解鎖圖示即可開啟"</string> + <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"已使用面孔解鎖。按解鎖圖示即可開啟。"</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> @@ -836,7 +833,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> @@ -913,8 +909,8 @@ <string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"不要新增圖塊"</string> <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"選取使用者"</string> <plurals name="fgs_manager_footer_label" formatted="false" msgid="9091110396713032871"> - <item quantity="other"><xliff:g id="COUNT_1">%s</xliff:g> 個使用中的應用程式</item> - <item quantity="one"><xliff:g id="COUNT_0">%s</xliff:g> 個使用中的應用程式</item> + <item quantity="other">有 <xliff:g id="COUNT_1">%s</xliff:g> 個應用程式正在使用</item> + <item quantity="one">有 <xliff:g id="COUNT_0">%s</xliff:g> 個應用程式正在使用</item> </plurals> <string name="fgs_dot_content_description" msgid="2865071539464777240">"新資料"</string> <string name="fgs_manager_dialog_title" msgid="5879184257257718677">"使用中的應用程式"</string> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index b1cf81e2e6d1..6e64ce3aef0d 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -836,7 +836,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 4f9262f7371d..f4b62e74e5ee 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -836,7 +836,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 24118d256fcc..a06201c44d72 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -179,12 +179,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/strings.xml b/packages/SystemUI/res/values/strings.xml index b248efe93e98..c2d7f8195468 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -888,6 +888,23 @@ <!-- 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> + + <!-- Title for add user confirmation dialog [CHAR LIMIT=30] --> + <string name="user_add_user_title" msgid="2108112641783146007">Add new user?</string> + + <!-- Message for add user confirmation dialog - short version. [CHAR LIMIT=none] --> + <string name="user_add_user_message_short" msgid="1511354412249044381">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> + + <!-- 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> @@ -2262,8 +2279,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 f97bbee3b152..7cd2158fd1a3 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/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/Prefs.java b/packages/SystemUI/src/com/android/systemui/Prefs.java index ff5715c606b6..9aa5fae1044d 100644 --- a/packages/SystemUI/src/com/android/systemui/Prefs.java +++ b/packages/SystemUI/src/com/android/systemui/Prefs.java @@ -63,7 +63,6 @@ public final class Prefs { Key.QS_WORK_ADDED, Key.QS_NIGHTDISPLAY_ADDED, Key.QS_LONG_PRESS_TOOLTIP_SHOWN_COUNT, - Key.SEEN_MULTI_USER, Key.SEEN_RINGER_GUIDANCE_COUNT, Key.QS_HAS_TURNED_OFF_MOBILE_DATA, Key.TOUCHED_RINGER_TOGGLE, @@ -106,7 +105,6 @@ public final class Prefs { * Settings panel. */ String QS_LONG_PRESS_TOOLTIP_SHOWN_COUNT = "QsLongPressTooltipShownCount"; - String SEEN_MULTI_USER = "HasSeenMultiUser"; String SEEN_RINGER_GUIDANCE_COUNT = "RingerGuidanceCount"; String QS_TILE_SPECS_REVEALED = "QsTileSpecsRevealed"; String QS_HAS_TURNED_OFF_MOBILE_DATA = "QsHasTurnedOffMobileData"; 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/touch/BouncerSwipeTouchHandler.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java index 990f04b58f95..2c5c3cdf3554 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java @@ -142,6 +142,9 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler { private void setPanelExpansion(float expansion) { mCurrentExpansion = expansion; + + mCentralSurfaces.setBouncerShowing(expansion != KeyguardBouncer.EXPANSION_HIDDEN); + mStatusBarKeyguardViewManager.onPanelExpansionChanged(mCurrentExpansion, false, true); } 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 0edadcc82a24..9e4ee61669a1 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java @@ -118,9 +118,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { mCheckBox.setVisibility(View.GONE); mStatusIcon.setVisibility(View.GONE); mContainerLayout.setOnClickListener(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)); @@ -141,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*/, @@ -156,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 */); @@ -164,34 +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 */); + mCheckBox.setOnCheckedChangeListener(null); mCheckBox.setVisibility(View.VISIBLE); mCheckBox.setChecked(true); - mSeekBar.setOnClickListener(null); - mSeekBar.setOnClickListener(v -> onGroupActionTriggered(false, device)); - setCheckBoxColor(mCheckBox, mController.getColorItemContent()); + mCheckBox.setOnCheckedChangeListener((buttonView, isChecked) -> { + onCheckBoxClicked(false, device); + }); + setCheckBoxColor(mCheckBox, mController.getColorActiveItem()); initSeekbar(device); } 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); mCurrentActivePosition = position; } else if (isDeviceIncluded(mController.getSelectableMediaDevice(), device)) { + mCheckBox.setOnCheckedChangeListener(null); mCheckBox.setVisibility(View.VISIBLE); mCheckBox.setChecked(false); - 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)); @@ -209,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 */); @@ -221,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(), 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 5c536d469212..958e9ed9e38b 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java @@ -183,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); @@ -381,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 bde772d95674..79be916b3137 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java @@ -218,9 +218,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 ec2a950051b7..af52a2fdc779 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java @@ -117,12 +117,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, @@ -147,18 +146,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) { @@ -338,7 +335,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)); } @@ -373,32 +371,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/media/dialog/MediaOutputSeekbar.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSeekbar.java deleted file mode 100644 index 0a3c5bf24b8b..000000000000 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSeekbar.java +++ /dev/null @@ -1,68 +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 com.android.systemui.media.dialog; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.widget.SeekBar; - -/** - * Customized seekbar used by MediaOutputDialog, which only changes progress when dragging, - * otherwise performs click. - */ -public class MediaOutputSeekbar extends SeekBar { - private static final int DRAGGING_THRESHOLD = 20; - private boolean mIsDragging = false; - - public MediaOutputSeekbar(Context context) { - super(context); - } - - public MediaOutputSeekbar(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - int width = getWidth() - - getPaddingLeft() - - getPaddingRight(); - int thumbPos = getPaddingLeft() - + width - * getProgress() - / getMax(); - if (event.getAction() == MotionEvent.ACTION_DOWN - && Math.abs(event.getX() - thumbPos) < DRAGGING_THRESHOLD) { - mIsDragging = true; - super.onTouchEvent(event); - } else if (event.getAction() == MotionEvent.ACTION_MOVE && mIsDragging) { - super.onTouchEvent(event); - } else if (event.getAction() == MotionEvent.ACTION_UP && mIsDragging) { - mIsDragging = false; - super.onTouchEvent(event); - } else if (event.getAction() == MotionEvent.ACTION_UP && !mIsDragging) { - performClick(); - } - return true; - } - - @Override - public boolean performClick() { - return super.performClick(); - } -} diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ChipStateReceiver.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ChipStateReceiver.kt index a0e803f6bb8d..40ea1e6e87df 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ChipStateReceiver.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ChipStateReceiver.kt @@ -17,6 +17,7 @@ package com.android.systemui.media.taptotransfer.receiver import android.app.StatusBarManager +import android.util.Log import com.android.internal.logging.UiEventLogger /** @@ -25,15 +26,15 @@ import com.android.internal.logging.UiEventLogger */ enum class ChipStateReceiver( @StatusBarManager.MediaTransferSenderState val stateInt: Int, - val uiEvent: UiEventLogger.UiEventEnum, + val uiEvent: UiEventLogger.UiEventEnum ) { CLOSE_TO_SENDER( StatusBarManager.MEDIA_TRANSFER_RECEIVER_STATE_CLOSE_TO_SENDER, - MediaTttReceiverUiEvents.MEDIA_TTT_RECEIVER_CLOSE_TO_SENDER, + MediaTttReceiverUiEvents.MEDIA_TTT_RECEIVER_CLOSE_TO_SENDER ), FAR_FROM_SENDER( StatusBarManager.MEDIA_TRANSFER_RECEIVER_STATE_FAR_FROM_SENDER, - MediaTttReceiverUiEvents.MEDIA_TTT_RECEIVER_FAR_FROM_SENDER, + MediaTttReceiverUiEvents.MEDIA_TTT_RECEIVER_FAR_FROM_SENDER ); companion object { @@ -43,8 +44,13 @@ enum class ChipStateReceiver( */ fun getReceiverStateFromId( @StatusBarManager.MediaTransferReceiverState displayState: Int - ) : ChipStateReceiver = values().first { it.stateInt == displayState } - + ): ChipStateReceiver? = + try { + values().first { it.stateInt == displayState } + } catch (e: NoSuchElementException) { + Log.e(TAG, "Could not find requested state $displayState", e) + null + } /** * Returns the state int from [StatusBarManager] associated with the given sender state @@ -56,3 +62,5 @@ enum class ChipStateReceiver( fun getReceiverStateIdFromName(name: String): Int = valueOf(name).stateInt } } + +private const val TAG = "ChipStateReceiver" 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/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/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/phone/CentralSurfaces.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java index c77b0d6721fb..eefa10bf495a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java @@ -3467,9 +3467,7 @@ public class CentralSurfaces extends CoreStartable implements mStatusBarHideIconsForBouncerManager.setBouncerShowingAndTriggerUpdate(bouncerShowing); mCommandQueue.recomputeDisableFlags(mDisplayId, true /* animate */); updateScrimController(); - if (!mBouncerShowing) { - updatePanelExpansionForKeyguard(); - } + updateNotificationPanelTouchState(); } /** @@ -3614,10 +3612,13 @@ public class CentralSurfaces extends CoreStartable implements * collapse the panel after we expanded it, and thus we would end up with a blank * Keyguard. */ - void updateNotificationPanelTouchState() { + public void updateNotificationPanelTouchState() { boolean goingToSleepWithoutAnimation = isGoingToSleep() && !mDozeParameters.shouldControlScreenOff(); - boolean disabled = (!mDeviceInteractive && !mDozeServiceHost.isPulsing()) + boolean bouncerShowingOverDream = isBouncerShowing() + && mDreamOverlayStateController.isOverlayActive(); + boolean disabled = bouncerShowingOverDream + || (!mDeviceInteractive && !mDozeServiceHost.isPulsing()) || goingToSleepWithoutAnimation; mNotificationPanelViewController.setTouchAndAnimationDisabled(disabled); mNotificationIconAreaController.setAnimationsEnabled(!disabled); 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 518a9181ec98..c850755d7f8e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java @@ -418,6 +418,8 @@ public abstract class PanelViewController { expand = false; } else if (onKeyguard) { expand = true; + } else if (mCentralSurfaces.isBouncerShowingOverDream()) { + expand = false; } else if (mKeyguardStateController.isKeyguardFadingAway()) { // If we're in the middle of dismissing the keyguard, don't expand due to the // cancelled gesture. Gesture cancellation during an unlock is expected in some 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/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/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java index 846e07fa0bad..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,9 +64,8 @@ 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.Prefs; -import com.android.systemui.Prefs.Key; import com.android.systemui.R; import com.android.systemui.SystemUISecondaryUserService; import com.android.systemui.animation.DialogLaunchAnimator; @@ -84,6 +84,7 @@ import com.android.systemui.settings.UserTracker; import com.android.systemui.statusbar.phone.SystemUIDialog; import com.android.systemui.telephony.TelephonyListenerManager; import com.android.systemui.user.CreateUserActivity; +import com.android.systemui.util.settings.GlobalSettings; import com.android.systemui.util.settings.SecureSettings; import java.io.PrintWriter; @@ -121,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; @@ -144,6 +147,7 @@ public class UserSwitcherController implements Dumpable { // When false, there won't be any visual affordance to add a new user from the keyguard even if // the user is unlocked private boolean mAddUsersFromLockScreen; + private boolean mUserSwitcherEnabled; @VisibleForTesting boolean mPauseRefreshUsers; private int mSecondaryUser = UserHandle.USER_NULL; @@ -160,6 +164,7 @@ public class UserSwitcherController implements Dumpable { private FalsingManager mFalsingManager; private View mView; private String mCreateSupervisedUserPackage; + private GlobalSettings mGlobalSettings; @Inject public UserSwitcherController(Context context, @@ -177,13 +182,16 @@ public class UserSwitcherController implements Dumpable { FalsingManager falsingManager, TelephonyListenerManager telephonyListenerManager, SecureSettings secureSettings, + GlobalSettings globalSettings, @Background Executor bgExecutor, @LongRunning Executor longRunningExecutor, @Main Executor uiExecutor, InteractionJankMonitor interactionJankMonitor, LatencyTracker latencyTracker, DumpManager dumpManager, - DialogLaunchAnimator dialogLaunchAnimator) { + DialogLaunchAnimator dialogLaunchAnimator, + GuestResumeSessionReceiver guestResumeSessionReceiver, + GuestResetOrExitSessionReceiver guestResetOrExitSessionReceiver) { mContext = context; mActivityManager = activityManager; mUserTracker = userTracker; @@ -194,14 +202,14 @@ public class UserSwitcherController implements Dumpable { mFalsingManager = falsingManager; mInteractionJankMonitor = interactionJankMonitor; mLatencyTracker = latencyTracker; - mGuestResumeSessionReceiver = new GuestResumeSessionReceiver( - this, mUserTracker, mUiEventLogger, secureSettings); + mGuestResumeSessionReceiver = guestResumeSessionReceiver; + mGuestResetOrExitSessionReceiver = guestResetOrExitSessionReceiver; + mGlobalSettings = globalSettings; 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(); @@ -237,8 +245,10 @@ public class UserSwitcherController implements Dumpable { @Override public void onChange(boolean selfChange) { mSimpleUserSwitcher = shouldUseSimpleUserSwitcher(); - mAddUsersFromLockScreen = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.ADD_USERS_WHEN_LOCKED, 0) != 0; + mAddUsersFromLockScreen = mGlobalSettings.getIntForUser( + Settings.Global.ADD_USERS_WHEN_LOCKED, 0, UserHandle.USER_SYSTEM) != 0; + mUserSwitcherEnabled = mGlobalSettings.getIntForUser( + Settings.Global.USER_SWITCHER_ENABLED, 0, UserHandle.USER_SYSTEM) != 0; refreshUsers(UserHandle.USER_NULL); }; }; @@ -246,6 +256,9 @@ public class UserSwitcherController implements Dumpable { Settings.Global.getUriFor(SIMPLE_USER_SWITCHER_GLOBAL_SETTING), true, mSettingsObserver); mContext.getContentResolver().registerContentObserver( + Settings.Global.getUriFor(Settings.Global.USER_SWITCHER_ENABLED), true, + mSettingsObserver); + mContext.getContentResolver().registerContentObserver( Settings.Global.getUriFor(Settings.Global.ADD_USERS_WHEN_LOCKED), true, mSettingsObserver); mContext.getContentResolver().registerContentObserver( @@ -266,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. * @@ -314,6 +331,10 @@ public class UserSwitcherController implements Dumpable { for (UserInfo info : infos) { boolean isCurrent = currentId == info.id; boolean switchToEnabled = canSwitchUsers || isCurrent; + if (!mUserSwitcherEnabled && !info.isPrimary()) { + continue; + } + if (info.isEnabled()) { if (info.isGuest()) { // Tapping guest icon triggers remove and a user switch therefore @@ -340,9 +361,6 @@ public class UserSwitcherController implements Dumpable { } } } - if (records.size() > 1 || guestRecord != null) { - Prefs.putBoolean(mContext, Key.SEEN_MULTI_USER, true); - } if (guestRecord == null) { if (mGuestUserAutoCreated) { @@ -411,12 +429,14 @@ public class UserSwitcherController implements Dumpable { } boolean canCreateGuest(boolean hasExistingGuest) { - return (currentUserCanCreateUsers() || anyoneCanCreateUsers()) + return mUserSwitcherEnabled + && (currentUserCanCreateUsers() || anyoneCanCreateUsers()) && !hasExistingGuest; } boolean canCreateUser() { - return (currentUserCanCreateUsers() || anyoneCanCreateUsers()) + return mUserSwitcherEnabled + && (currentUserCanCreateUsers() || anyoneCanCreateUsers()) && mUserManager.canAddMoreUsers(UserManager.USER_TYPE_FULL_SECONDARY); } @@ -509,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. @@ -544,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); @@ -552,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 { @@ -792,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; @@ -959,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); @@ -978,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); + } } } } @@ -1001,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) { @@ -1034,8 +1126,8 @@ public class UserSwitcherController implements Dumpable { private boolean shouldUseSimpleUserSwitcher() { int defaultSimpleUserSwitcher = mContext.getResources().getBoolean( com.android.internal.R.bool.config_expandLockScreenUserSwitcher) ? 1 : 0; - return Settings.Global.getInt(mContext.getContentResolver(), - SIMPLE_USER_SWITCHER_GLOBAL_SETTING, defaultSimpleUserSwitcher) != 0; + return mGlobalSettings.getIntForUser(SIMPLE_USER_SWITCHER_GLOBAL_SETTING, + defaultSimpleUserSwitcher, UserHandle.USER_SYSTEM) != 0; } public void startActivity(Intent intent) { @@ -1146,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 @@ -1173,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); + } } } } @@ -1187,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/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/dreams/touch/BouncerSwipeTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java index a016a1d8ca70..761a2c2c8e04 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 @@ -160,6 +160,28 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase { 2)).isTrue(); } + /** + * Ensures {@link CentralSurfaces} + */ + @Test + public void testInformBouncerShowingOnExpand() { + swipeToPosition(1f, Direction.UP, 0); + verify(mCentralSurfaces).setBouncerShowing(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).setBouncerShowing(false); + } + private enum Direction { DOWN, UP, @@ -397,6 +419,7 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase { } 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/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt index 067607f9b8ae..9edc4f4c71c3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt @@ -102,7 +102,7 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() { TapGestureDetector(context), powerManager, Handler.getMain(), - receiverUiEventLogger, + receiverUiEventLogger ) val callbackCaptor = ArgumentCaptor.forClass(CommandQueue.Callbacks::class.java) @@ -206,6 +206,18 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() { assertThat(chipView.getAppIconView().measuredHeight).isEqualTo(expectedSize) } + @Test + fun commandQueueCallback_invalidStateParam_noChipShown() { + commandQueueCallback.updateMediaTapToTransferReceiverDisplay( + StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED, + routeInfo, + null, + APP_NAME + ) + + verify(windowManager, never()).addView(any(), any()) + } + private fun getChipView(): ViewGroup { val viewCaptor = ArgumentCaptor.forClass(View::class.java) verify(windowManager).addView(viewCaptor.capture(), any()) 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 a2a02cd939ef..30c01b5ba575 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java @@ -816,8 +816,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/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/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 799dafcd01b8..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 @@ -28,6 +29,7 @@ import android.hardware.fingerprint.FingerprintManager import android.os.Handler import android.os.UserHandle import android.os.UserManager +import android.provider.Settings import android.testing.AndroidTestingRunner import android.testing.TestableLooper import android.view.ThreadedRenderer @@ -36,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 @@ -51,6 +55,7 @@ import com.android.systemui.settings.UserTracker import com.android.systemui.statusbar.phone.NotificationShadeWindowView import com.android.systemui.telephony.TelephonyListenerManager import com.android.systemui.util.concurrency.FakeExecutor +import com.android.systemui.util.settings.GlobalSettings import com.android.systemui.util.settings.SecureSettings import com.android.systemui.util.time.FakeSystemClock import org.junit.Assert.assertEquals @@ -67,6 +72,7 @@ import org.mockito.Mockito.`when` import org.mockito.Mockito.any import org.mockito.Mockito.doNothing import org.mockito.Mockito.doReturn +import org.mockito.Mockito.eq import org.mockito.Mockito.mock import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @@ -95,6 +101,12 @@ class UserSwitcherControllerTest : SysuiTestCase() { @Mock private lateinit var notificationShadeWindowView: NotificationShadeWindowView @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 @@ -126,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) @@ -148,6 +179,22 @@ class UserSwitcherControllerTest : SysuiTestCase() { `when`(userTracker.userId).thenReturn(ownerId) `when`(userTracker.userInfo).thenReturn(ownerInfo) + `when`( + globalSettings.getIntForUser( + eq(Settings.Global.ADD_USERS_WHEN_LOCKED), + anyInt(), + eq(UserHandle.USER_SYSTEM) + ) + ).thenReturn(0) + + `when`( + globalSettings.getIntForUser( + eq(Settings.Global.USER_SWITCHER_ENABLED), + anyInt(), + eq(UserHandle.USER_SYSTEM) + ) + ).thenReturn(1) + setupController() } @@ -168,13 +215,16 @@ class UserSwitcherControllerTest : SysuiTestCase() { falsingManager, telephonyListenerManager, secureSettings, + globalSettings, bgExecutor, longRunningExecutor, uiExecutor, interactionJankMonitor, latencyTracker, dumpManager, - dialogLaunchAnimator) + dialogLaunchAnimator, + guestResumeSessionReceiver, + guestResetOrExitSessionReceiver) userSwitcherController.init(notificationShadeWindowView) } @@ -264,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 @@ -326,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()) } @@ -469,4 +522,43 @@ class UserSwitcherControllerTest : SysuiTestCase() { // THEN a supervised user can NOT be constructed assertFalse(userSwitcherController.canCreateSupervisedUser()) } + + @Test + fun testCannotCreateUserWhenUserSwitcherDisabled() { + `when`( + globalSettings.getIntForUser( + eq(Settings.Global.USER_SWITCHER_ENABLED), + anyInt(), + eq(UserHandle.USER_SYSTEM) + ) + ).thenReturn(0) + setupController() + assertFalse(userSwitcherController.canCreateUser()) + } + + @Test + fun testCannotCreateGuestUserWhenUserSwitcherDisabled() { + `when`( + globalSettings.getIntForUser( + eq(Settings.Global.USER_SWITCHER_ENABLED), + anyInt(), + eq(UserHandle.USER_SYSTEM) + ) + ).thenReturn(0) + setupController() + assertFalse(userSwitcherController.canCreateGuest(false)) + } + + @Test + fun testCannotCreateSupervisedUserWhenUserSwitcherDisabled() { + `when`( + globalSettings.getIntForUser( + eq(Settings.Global.USER_SWITCHER_ENABLED), + anyInt(), + eq(UserHandle.USER_SYSTEM) + ) + ).thenReturn(0) + setupController() + assertFalse(userSwitcherController.canCreateSupervisedUser()) + } } 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..4ca83dde8b30 100644 --- a/proto/src/system_messages.proto +++ b/proto/src/system_messages.proto @@ -286,6 +286,11 @@ 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; 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 6846b2e3e6f7..03de43c11476 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 13a5a2829945..6696d374580a 100644 --- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java @@ -97,6 +97,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; @@ -128,7 +130,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; @@ -162,6 +166,7 @@ public class CompanionDeviceManagerService extends SystemService { mUserPersistenceHandler = new PersistUserStateHandler(); mAssociationStore = new AssociationStoreImpl(); + mSystemDataTransferRequestStore = new SystemDataTransferRequestStore(); } @Override @@ -176,6 +181,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( @@ -600,6 +607,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); @@ -851,6 +870,9 @@ public class CompanionDeviceManagerService extends SystemService { // Removing the association. mAssociationStore.removeAssociation(associationId); + // 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 d0cc12286b12..2487befecf52 100644 --- a/services/companion/java/com/android/server/companion/PersistentDataStore.java +++ b/services/companion/java/com/android/server/companion/PersistentDataStore.java @@ -101,7 +101,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/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/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index cddd019093c7..bd7b10a65e73 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -8731,8 +8731,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"); } } 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/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/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index c88e3eb6d507..67268e23c5b9 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -63,6 +63,7 @@ import com.android.internal.display.BrightnessSynchronizer; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.util.FrameworkStatsLog; +import com.android.internal.util.RingBuffer; import com.android.server.LocalServices; import com.android.server.am.BatteryStatsService; import com.android.server.display.RampAnimator.DualRampAnimator; @@ -156,6 +157,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call private static final int REPORTED_TO_POLICY_SCREEN_ON = 2; private static final int REPORTED_TO_POLICY_SCREEN_TURNING_OFF = 3; + private static final int RINGBUFFER_MAX = 100; + private final String TAG; private final Object mLock = new Object(); @@ -213,6 +216,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call private final float mScreenBrightnessDefault; + // Previously logged screen brightness. Used for autobrightness event dumpsys. + private float mPreviousScreenBrightness = Float.NaN; + // The minimum allowed brightness while in VR. private final float mScreenBrightnessForVrRangeMinimum; @@ -388,6 +394,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call private final Runnable mOnBrightnessChangeRunnable; + // Used for keeping record in dumpsys for when and to which brightness auto adaptions were made. + private RingBuffer<AutobrightnessEvent> mAutobrightnessEventRingBuffer; + // A record of state for skipping brightness ramps. private int mSkipRampState = RAMP_STATE_SKIP_NONE; @@ -981,6 +990,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mHbmController, mBrightnessThrottler, mIdleModeBrightnessMapper, mDisplayDeviceConfig.getAmbientHorizonShort(), mDisplayDeviceConfig.getAmbientHorizonLong()); + + mAutobrightnessEventRingBuffer = + new RingBuffer<>(AutobrightnessEvent.class, RINGBUFFER_MAX); } else { mUseSoftwareAutoBrightnessConfig = false; } @@ -1555,6 +1567,15 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call Slog.v(TAG, "Brightness [" + brightnessState + "] manual adjustment."); } + // Add any automatic changes to autobrightness ringbuffer for dumpsys. + if (mBrightnessReason.reason == BrightnessReason.REASON_AUTOMATIC + && !BrightnessSynchronizer.floatEquals( + mPreviousScreenBrightness, brightnessState)) { + mPreviousScreenBrightness = brightnessState; + mAutobrightnessEventRingBuffer.append(new AutobrightnessEvent( + System.currentTimeMillis(), brightnessState)); + } + // Update display white-balance. if (mDisplayWhiteBalanceController != null) { if (state == Display.STATE_ON && mDisplayWhiteBalanceSettings.isEnabled()) { @@ -2482,6 +2503,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call if (mAutomaticBrightnessController != null) { mAutomaticBrightnessController.dump(pw); + dumpAutobrightnessEvents(pw); } if (mHbmController != null) { @@ -2538,6 +2560,20 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } } + private void dumpAutobrightnessEvents(PrintWriter pw) { + int size = mAutobrightnessEventRingBuffer.size(); + if (size < 1) { + pw.println("No Automatic Brightness Adjustments"); + return; + } + + pw.println("Automatic Brightness Adjustments Last " + size + " Events: "); + AutobrightnessEvent[] eventArray = mAutobrightnessEventRingBuffer.toArray(); + for (int i = 0; i < mAutobrightnessEventRingBuffer.size(); i++) { + pw.println(" " + eventArray[i].toString()); + } + } + private static float clampAbsoluteBrightness(float value) { return MathUtils.constrain(value, PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX); @@ -2610,6 +2646,21 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } } + private static class AutobrightnessEvent { + final long mTime; + final float mBrightness; + + AutobrightnessEvent(long time, float brightness) { + mTime = time; + mBrightness = brightness; + } + + @Override + public String toString() { + return TimeUtils.formatForLogging(mTime) + " - Brightness: " + mBrightness; + } + } + private final class DisplayControllerHandler extends Handler { public DisplayControllerHandler(Looper looper) { super(looper, null, true /*async*/); 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 a155095c0725..84bce8098202 100644 --- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java +++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java @@ -195,6 +195,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; @@ -635,6 +637,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); @@ -815,6 +818,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 @@ -829,6 +833,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. @@ -1094,6 +1108,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..e433324b152d 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; @@ -157,6 +158,8 @@ public class InputManagerService extends IInputManager.Stub // 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 +361,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 +411,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 +885,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. @@ -2343,7 +2355,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 +2371,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 3c3140551bc3..8cf0ab744124 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -4734,7 +4734,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)) { @@ -4742,10 +4743,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); } @@ -4763,7 +4761,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); } @@ -6571,11 +6569,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/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java index 42fed365441b..9e5da450c8a5 100644 --- a/services/core/java/com/android/server/media/MediaSessionService.java +++ b/services/core/java/com/android/server/media/MediaSessionService.java @@ -1179,8 +1179,15 @@ public class MediaSessionService extends SystemService implements Monitor { @Override public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver) { - (new MediaShellCommand()).exec(this, in, out, err, args, callback, - resultReceiver); + String[] packageNames = + mContext.getPackageManager().getPackagesForUid(Binder.getCallingUid()); + String packageName = packageNames != null && packageNames.length > 0 + ? packageNames[0] + : "com.android.shell"; // We should not need this branch, but defaulting to the + // current shell package name for robustness. See + // b/227109905. + new MediaShellCommand(packageName) + .exec(this, in, out, err, args, callback, resultReceiver); } @Override diff --git a/services/core/java/com/android/server/media/MediaShellCommand.java b/services/core/java/com/android/server/media/MediaShellCommand.java index 103cdd997efc..d175d87651de 100644 --- a/services/core/java/com/android/server/media/MediaShellCommand.java +++ b/services/core/java/com/android/server/media/MediaShellCommand.java @@ -47,15 +47,19 @@ import java.util.List; * ShellCommand for MediaSessionService. */ public class MediaShellCommand extends ShellCommand { - // This doesn't belongs to any package. Setting the package name to empty string. - private static final String PACKAGE_NAME = ""; private static ActivityThread sThread; private static MediaSessionManager sMediaSessionManager; + + private final String mPackageName; private ISessionManager mSessionService; private PrintWriter mWriter; private PrintWriter mErrorWriter; private InputStream mInput; + public MediaShellCommand(String packageName) { + mPackageName = packageName; + } + @Override public int onCommand(String cmd) { mWriter = getOutPrintWriter(); @@ -110,7 +114,7 @@ public class MediaShellCommand extends ShellCommand { mWriter.println(); mWriter.println("media_session dispatch: dispatch a media key to the system."); mWriter.println(" KEY may be: play, pause, play-pause, mute, headsethook,"); - mWriter.println(" stop, next, previous, rewind, record, fast-forword."); + mWriter.println(" stop, next, previous, rewind, record, fast-forward."); mWriter.println("media_session list-sessions: print a list of the current sessions."); mWriter.println("media_session monitor: monitor updates to the specified session."); mWriter.println(" Use the tag from list-sessions."); @@ -120,7 +124,8 @@ public class MediaShellCommand extends ShellCommand { private void sendMediaKey(KeyEvent event) { try { - mSessionService.dispatchMediaKeyEvent(PACKAGE_NAME, false, event, false); + mSessionService.dispatchMediaKeyEvent( + mPackageName, /* asSystemService= */ false, event, /* needWakeLock= */ false); } catch (RemoteException e) { } } 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/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..9ba1552eaa7f 100644 --- a/services/core/java/com/android/server/om/OverlayManagerService.java +++ b/services/core/java/com/android/server/om/OverlayManagerService.java @@ -1477,7 +1477,7 @@ 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 = @@ -1493,6 +1493,9 @@ public final class OverlayManagerService extends SystemService { } 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..e15e65ab711e 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; @@ -785,15 +788,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 +814,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 +829,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/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java index a91c55fb895d..e07e3c103f5f 100644 --- a/services/core/java/com/android/server/pm/ApexManager.java +++ b/services/core/java/com/android/server/pm/ApexManager.java @@ -119,16 +119,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,7 +138,8 @@ public abstract class ApexManager { apexInfo.moduleName, new File(Environment.getApexDirectory() + File.separator + apexInfo.moduleName), - new File(apexInfo.preinstalledModulePath)); + new File(apexInfo.preinstalledModulePath), + apexInfo.isFactory); } } @@ -211,7 +214,7 @@ public abstract class ApexManager { * @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; + return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) == 0; } /** @@ -503,7 +506,7 @@ public abstract class ApexManager { * @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; + return packageInfo.isActiveApex; } /** @@ -1150,7 +1153,7 @@ public abstract class ApexManager { // Installation was successful, time to update mAllPackagesCache synchronized (mLock) { if (isFactory(existingApexPkg)) { - existingApexPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED; + existingApexPkg.isActiveApex = false; mAllPackagesCache.add(finalApexPkg); } else { for (int i = 0, size = mAllPackagesCache.size(); i < size; i++) { diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java index 80d61b593fd2..a548b728e20d 100644 --- a/services/core/java/com/android/server/pm/ComputerEngine.java +++ b/services/core/java/com/android/server/pm/ComputerEngine.java @@ -540,8 +540,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); @@ -1835,9 +1840,6 @@ public class ComputerEngine implements Computer { list.addAll(mApexManager.getFactoryPackages()); } else { list.addAll(mApexManager.getActivePackages()); - if (listUninstalled) { - list.addAll(mApexManager.getInactivePackages()); - } } } return new ParceledListSlice<>(list); @@ -4345,11 +4347,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)) { diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java index 7dae22a44cc5..52d4873f80fd 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; @@ -762,7 +761,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 */); @@ -822,18 +820,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/InitAppsHelper.java b/services/core/java/com/android/server/pm/InitAppsHelper.java index d279c77ad304..3dd0022c28cf 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; @@ -168,7 +169,11 @@ 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; diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java index 77d37dc377a2..3b759470ba83 100644 --- a/services/core/java/com/android/server/pm/InstallPackageHelper.java +++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java @@ -60,6 +60,7 @@ 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_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; @@ -101,7 +102,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; @@ -315,6 +315,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. @@ -2341,29 +2347,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; 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/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 e1af9a7ab96f..8e1301749aaa 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,7 @@ 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; @IntDef(flag = true, prefix = { "SCAN_" }, value = { SCAN_NO_DEX, @@ -690,10 +689,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; @@ -1842,10 +1837,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 @@ -3141,23 +3136,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); - } - } - VersionInfo getSettingsVersionForPackage(AndroidPackage pkg) { if (pkg.isExternalStorage()) { if (TextUtils.isEmpty(pkg.getVolumeUuid())) { @@ -6270,11 +6248,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 @@ -6482,85 +6461,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( 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..8302c2b4e76b 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); } /** 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 b53cfc558f6e..383e4a56d993 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 ee0fdc07f841..b6e633cb1b73 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/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java index 849f53026c99..16cf721ffc7e 100644 --- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java +++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java @@ -1022,7 +1022,8 @@ final class DefaultPermissionGrantPolicy { } for (String packageName : packageNames) { grantPermissionsToSystemPackage(NO_PM_CACHE, packageName, userId, - PHONE_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS, SMS_PERMISSIONS, + PHONE_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS, SMS_PERMISSIONS); + grantPermissionsToPackage(NO_PM_CACHE, packageName, userId, false, false, NOTIFICATION_PERMISSIONS); } } 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 c524fb7ae9e5..a963280c7991 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; @@ -3240,9 +3239,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/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index ad56f199c269..6e78ecb83005 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -524,9 +524,6 @@ public final class PowerManagerService extends SystemService // The screen off timeout setting value in milliseconds. private long mScreenOffTimeoutSetting; - // The screen off timeout setting value in milliseconds to apply while device is docked. - private long mScreenOffTimeoutDockedSetting; - // Default for attentive warning duration. private long mAttentiveWarningDurationConfig; @@ -1289,9 +1286,6 @@ public final class PowerManagerService extends SystemService resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.SCREEN_OFF_TIMEOUT), false, mSettingsObserver, UserHandle.USER_ALL); - resolver.registerContentObserver(Settings.System.getUriFor( - Settings.System.SCREEN_OFF_TIMEOUT_DOCKED), - false, mSettingsObserver, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.Secure.getUriFor( Settings.Secure.SLEEP_TIMEOUT), false, mSettingsObserver, UserHandle.USER_ALL); @@ -1414,9 +1408,6 @@ public final class PowerManagerService extends SystemService mScreenOffTimeoutSetting = Settings.System.getIntForUser(resolver, Settings.System.SCREEN_OFF_TIMEOUT, DEFAULT_SCREEN_OFF_TIMEOUT, UserHandle.USER_CURRENT); - mScreenOffTimeoutDockedSetting = Settings.System.getLongForUser(resolver, - Settings.System.SCREEN_OFF_TIMEOUT_DOCKED, mScreenOffTimeoutSetting, - UserHandle.USER_CURRENT); mSleepTimeoutSetting = Settings.Secure.getIntForUser(resolver, Settings.Secure.SLEEP_TIMEOUT, DEFAULT_SLEEP_TIMEOUT, UserHandle.USER_CURRENT); @@ -2999,9 +2990,7 @@ public final class PowerManagerService extends SystemService @GuardedBy("mLock") private long getScreenOffTimeoutLocked(long sleepTimeout, long attentiveTimeout) { - long timeout = mDockState == Intent.EXTRA_DOCK_STATE_UNDOCKED - ? mScreenOffTimeoutSetting - : mScreenOffTimeoutDockedSetting; + long timeout = mScreenOffTimeoutSetting; if (isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked()) { timeout = Math.min(timeout, mMaximumScreenOffTimeoutFromDeviceAdmin); } @@ -4946,8 +4935,7 @@ public final class PowerManagerService extends SystemService } } - @VisibleForTesting - final class DockReceiver extends BroadcastReceiver { + private final class DockReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { synchronized (mLock) { 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/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 6e205be5b574..feaa10dd94a0 100644 --- a/services/core/java/com/android/server/wm/BLASTSyncEngine.java +++ b/services/core/java/com/android/server/wm/BLASTSyncEngine.java @@ -193,12 +193,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/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index cc99f377bfee..079e1acc7de8 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -1976,23 +1976,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(); @@ -2006,7 +2006,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent> r.getDisplayContent().prepareAppTransition(TRANSIT_NONE); final boolean singleActivity = task.getChildCount() == 1; - final Task rootTask; if (singleActivity) { rootTask = task; @@ -2064,6 +2063,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. @@ -2074,13 +2076,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. @@ -2098,9 +2093,23 @@ class RootWindowContainer extends WindowContainer<DisplayContent> r.supportsEnterPipOnTaskSwitch = false; } 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/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java index 8a0ae65267a3..70545c9a577f 100644 --- a/services/core/java/com/android/server/wm/TaskOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java @@ -53,10 +53,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; @@ -318,13 +318,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 c44f08cbd1eb..4a0b343a95eb 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; @@ -670,8 +671,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); @@ -760,6 +759,8 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe } mSyncId = -1; mOverrideOptions = null; + + reportStartReasonsToLogger(); } /** @@ -972,11 +973,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); @@ -1595,6 +1600,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?). @@ -1624,6 +1642,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. */ @@ -1664,7 +1690,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/jni/Android.bp b/services/core/jni/Android.bp index 0d49f5fffb4b..cfcbc3ac0676 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -185,6 +185,7 @@ cc_defaults { "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 268d588bd907..b7005a52b081 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -11890,6 +11890,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/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 617321beadd2..7755552bcad2 100644 --- a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java @@ -558,6 +558,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/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/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/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..11acfb7af32a 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java @@ -386,7 +386,8 @@ public class ApexManagerTest { 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); @@ -396,7 +397,8 @@ public class ApexManagerTest { 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 @@ -424,7 +426,8 @@ public class ApexManagerTest { 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); @@ -434,7 +437,8 @@ public class ApexManagerTest { 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 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 a79a52c1c198..b91ff6bfb553 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. */ @@ -698,6 +703,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 3e81d601e477..37792c5f7963 100644 --- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java @@ -87,7 +87,6 @@ import com.android.server.lights.LightsManager; import com.android.server.policy.WindowManagerPolicy; import com.android.server.power.PowerManagerService.BatteryReceiver; import com.android.server.power.PowerManagerService.BinderService; -import com.android.server.power.PowerManagerService.DockReceiver; import com.android.server.power.PowerManagerService.Injector; import com.android.server.power.PowerManagerService.NativeWrapper; import com.android.server.power.PowerManagerService.UserSwitchedReceiver; @@ -151,7 +150,6 @@ public class PowerManagerServiceTest { private Resources mResourcesSpy; private OffsettableClock mClock; private TestLooper mTestLooper; - private DockReceiver mDockReceiver; private static class IntentFilterMatcher implements ArgumentMatcher<IntentFilter> { private final IntentFilter mFilter; @@ -338,14 +336,6 @@ public class PowerManagerServiceTest { argThat(new IntentFilterMatcher(usFilter)), isNull(), isA(Handler.class)); mUserSwitchedReceiver = userSwitchedCaptor.getValue(); - // Grab the DockReceiver - ArgumentCaptor<DockReceiver> dockReceiverCaptor = - ArgumentCaptor.forClass(DockReceiver.class); - IntentFilter dockFilter = new IntentFilter(Intent.ACTION_DOCK_EVENT); - verify(mContextSpy).registerReceiver(dockReceiverCaptor.capture(), - argThat(new IntentFilterMatcher(dockFilter)), isNull(), isA(Handler.class)); - mDockReceiver = dockReceiverCaptor.getValue(); - mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); } @@ -394,16 +384,6 @@ public class PowerManagerServiceTest { .thenReturn(minimumScreenOffTimeoutConfigMillis); } - private void setScreenOffTimeout(int screenOffTimeoutMillis) { - Settings.System.putInt(mContextSpy.getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT, - screenOffTimeoutMillis); - } - - private void setScreenOffTimeoutDocked(int screenOffTimeoutMillis) { - Settings.System.putInt(mContextSpy.getContentResolver(), - Settings.System.SCREEN_OFF_TIMEOUT_DOCKED, screenOffTimeoutMillis); - } - private void advanceTime(long timeMs) { mClock.fastForward(timeMs); mTestLooper.dispatchAll(); @@ -931,92 +911,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 testScreenOffTimeout_goesToSleepAfterTimeout() { - final DisplayInfo info = new DisplayInfo(); - info.displayGroupId = Display.DEFAULT_DISPLAY_GROUP; - when(mDisplayManagerInternalMock.getDisplayInfo(Display.DEFAULT_DISPLAY)).thenReturn(info); - - setMinimumScreenOffTimeoutConfig(10); - setScreenOffTimeout(10); - - createService(); - startSystem(); - - mService.getBinderServiceInstance().userActivity(Display.DEFAULT_DISPLAY, mClock.now(), - PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0); - assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); - advanceTime(15); - assertThat(mService.getGlobalWakefulnessLocked()).isNotEqualTo(WAKEFULNESS_AWAKE); - } - - @Test - public void testScreenOffTimeout_usesRegularTimeoutWhenNotDocked() { - final DisplayInfo info = new DisplayInfo(); - info.displayGroupId = Display.DEFAULT_DISPLAY_GROUP; - when(mDisplayManagerInternalMock.getDisplayInfo(Display.DEFAULT_DISPLAY)).thenReturn(info); - - setMinimumScreenOffTimeoutConfig(10); - setScreenOffTimeout(10); - setScreenOffTimeoutDocked(30); - - createService(); - startSystem(); - - mService.getBinderServiceInstance().userActivity(Display.DEFAULT_DISPLAY, mClock.now(), - PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0); - assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); - advanceTime(15); - assertThat(mService.getGlobalWakefulnessLocked()).isNotEqualTo(WAKEFULNESS_AWAKE); - } - - @Test - public void testScreenOffTimeout_usesDockedTimeoutWhenDocked() { - final DisplayInfo info = new DisplayInfo(); - info.displayGroupId = Display.DEFAULT_DISPLAY_GROUP; - when(mDisplayManagerInternalMock.getDisplayInfo(Display.DEFAULT_DISPLAY)).thenReturn(info); - - setMinimumScreenOffTimeoutConfig(10); - setScreenOffTimeout(10); - setScreenOffTimeoutDocked(30); - - createService(); - startSystem(); - - mService.getBinderServiceInstance().userActivity(Display.DEFAULT_DISPLAY, mClock.now(), - PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0); - mDockReceiver.onReceive(mContextSpy, - new Intent(Intent.ACTION_DOCK_EVENT).putExtra(Intent.EXTRA_DOCK_STATE, - Intent.EXTRA_DOCK_STATE_DESK)); - - assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); - advanceTime(15); - assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); - advanceTime(20); - assertThat(mService.getGlobalWakefulnessLocked()).isNotEqualTo(WAKEFULNESS_AWAKE); - } - - @Test public void testInattentiveSleep_goesToSleepWithWakeLock() { final String pkg = mContextSpy.getOpPackageName(); final Binder token = new Binder(); @@ -1039,6 +933,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/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/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/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/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 8d4a0176e3be..e6c2e049519b 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java @@ -506,6 +506,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) @@ -581,6 +582,7 @@ final class HotwordDetectionConnection { mValidatingDspTrigger = false; try { enforcePermissionsForDataDelivery(); + enforceExtraKeyphraseIdNotLeaked(result, recognitionEvent); } catch (SecurityException e) { HotwordMetricsLogger.writeKeyphraseTriggerEvent( mDetectorType, @@ -1130,6 +1132,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 07e18d524701..b3419e024125 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/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index d2ee71a6ddb5..5b3bde65700e 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -176,7 +176,7 @@ public class CarrierConfigManager { * This flag specifies whether VoLTE availability is based on provisioning. By default this is * false. * Used for UCE to determine if EAB provisioning checks should be based on provisioning. - * @deprecated Use {@link Ims#KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE} instead. + * @deprecated Use {@link Ims#KEY_CARRIER_RCS_PROVISIONING_REQUIRED_BOOL} instead. */ @Deprecated public static final String diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 7b5d62de58f2..7f0df82b9010 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -7742,7 +7742,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. 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 34158685b6d1..4439e5c35d83 100644 --- a/telephony/java/android/telephony/ims/ImsRcsManager.java +++ b/telephony/java/android/telephony/ims/ImsRcsManager.java @@ -18,6 +18,7 @@ package android.telephony.ims; import android.Manifest; import android.annotation.CallbackExecutor; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.RequiresFeature; import android.annotation.RequiresPermission; @@ -43,6 +44,8 @@ import android.util.Log; import com.android.internal.telephony.IIntegerConsumer; import com.android.internal.telephony.ITelephony; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.HashMap; import java.util.Map; import java.util.Objects; @@ -87,6 +90,46 @@ public class ImsRcsManager { "android.telephony.ims.action.SHOW_CAPABILITY_DISCOVERY_OPT_IN"; /** + * This carrier supports User Capability Exchange as, defined by the framework using a + * presence server. If set, the RcsFeature should support capability exchange. If not set, this + * RcsFeature should not publish capabilities or service capability requests. + * @hide + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = "CAPABILITY_TYPE_", flag = true, value = { + CAPABILITY_TYPE_NONE, + CAPABILITY_TYPE_OPTIONS_UCE, + CAPABILITY_TYPE_PRESENCE_UCE + }) + public @interface RcsImsCapabilityFlag {} + + /** + * Undefined capability type for initialization + */ + public static final int CAPABILITY_TYPE_NONE = 0; + + /** + * This carrier supports User Capability Exchange using SIP OPTIONS as defined by the + * framework. If set, the RcsFeature should support capability exchange using SIP OPTIONS. + * If not set, this RcsFeature should not service capability requests. + */ + public static final int CAPABILITY_TYPE_OPTIONS_UCE = 1 << 0; + + /** + * This carrier supports User Capability Exchange using a presence server as defined by the + * framework. If set, the RcsFeature should support capability exchange using a presence + * server. If not set, this RcsFeature should not publish capabilities or service capability + * requests using presence. + */ + public static final int CAPABILITY_TYPE_PRESENCE_UCE = 1 << 1; + + /** + * This is used to check the upper range of RCS capability + * @hide + */ + public static final int CAPABILITY_TYPE_MAX = CAPABILITY_TYPE_PRESENCE_UCE + 1; + + /** * An application can use {@link #addOnAvailabilityChangedListener} to register a * {@link OnAvailabilityChangedListener}, which will notify the user when the RCS feature * availability status updates from the ImsService. @@ -104,7 +147,7 @@ public class ImsRcsManager { * * @param capabilities The new availability of the capabilities. */ - void onAvailabilityChanged(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities); + void onAvailabilityChanged(@RcsImsCapabilityFlag int capabilities); } /** @@ -486,7 +529,7 @@ public class ImsRcsManager { */ @SystemApi @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) - public boolean isCapable(@RcsUceAdapter.RcsImsCapabilityFlag int capability, + public boolean isCapable(@RcsImsCapabilityFlag int capability, @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) throws ImsException { IImsRcsController imsRcsController = getIImsRcsController(); if (imsRcsController == null) { @@ -497,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", @@ -522,7 +567,7 @@ public class ImsRcsManager { */ @SystemApi @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) - public boolean isAvailable(@RcsUceAdapter.RcsImsCapabilityFlag int capability, + public boolean isAvailable(@RcsImsCapabilityFlag int capability, @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) throws ImsException { IImsRcsController imsRcsController = getIImsRcsController(); @@ -534,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 677c1a9a7d76..f2976f14d7a6 100644 --- a/telephony/java/android/telephony/ims/ProvisioningManager.java +++ b/telephony/java/android/telephony/ims/ProvisioningManager.java @@ -38,7 +38,6 @@ import android.telephony.ims.aidl.IFeatureProvisioningCallback; import android.telephony.ims.aidl.IImsConfigCallback; import android.telephony.ims.aidl.IRcsConfigCallback; import android.telephony.ims.feature.MmTelFeature; -import android.telephony.ims.feature.RcsFeature; import android.telephony.ims.stub.ImsConfigImplBase; import android.telephony.ims.stub.ImsRegistrationImplBase; @@ -55,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 { @@ -970,7 +972,7 @@ public class ProvisioningManager { /** * Callback for IMS provisioning feature changes. */ - public static class FeatureProvisioningCallback { + public abstract static class FeatureProvisioningCallback { private static class CallbackBinder extends IFeatureProvisioningCallback.Stub { @@ -1024,12 +1026,10 @@ public class ProvisioningManager { * specified, or {@code false} if the capability is not provisioned for the technology * specified. */ - public void onFeatureProvisioningChanged( + public abstract void onFeatureProvisioningChanged( @MmTelFeature.MmTelCapabilities.MmTelCapability int capability, @ImsRegistrationImplBase.ImsRegistrationTech int tech, - boolean isProvisioned) { - // Base Implementation - } + boolean isProvisioned); /** * The IMS RCS provisioning has changed for a specific capability and IMS @@ -1041,12 +1041,10 @@ public class ProvisioningManager { * specified, or {@code false} if the capability is not provisioned for the technology * specified. */ - public void onRcsFeatureProvisioningChanged( - @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability, + public abstract void onRcsFeatureProvisioningChanged( + @ImsRcsManager.RcsImsCapabilityFlag int capability, @ImsRegistrationImplBase.ImsRegistrationTech int tech, - boolean isProvisioned) { - // Base Implementation - } + boolean isProvisioned); /**@hide*/ public final IFeatureProvisioningCallback getBinder() { @@ -1505,7 +1503,7 @@ public class ProvisioningManager { * Get the provisioning status for the IMS RCS capability specified. * * If provisioning is not required for the queried - * {@link RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag} this method will always return + * {@link ImsRcsManager.RcsImsCapabilityFlag} this method will always return * {@code true}. * * @see CarrierConfigManager.Ims#KEY_CARRIER_RCS_PROVISIONING_REQUIRED_BOOL @@ -1522,7 +1520,7 @@ public class ProvisioningManager { @WorkerThread @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean getRcsProvisioningStatusForCapability( - @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability) { + @ImsRcsManager.RcsImsCapabilityFlag int capability) { try { return getITelephony().getRcsProvisioningStatusForCapability(mSubId, capability, ImsRegistrationImplBase.REGISTRATION_TECH_LTE); @@ -1535,7 +1533,7 @@ public class ProvisioningManager { * Get the provisioning status for the IMS RCS capability specified. * * If provisioning is not required for the queried - * {@link RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag} this method + * {@link ImsRcsManager.RcsImsCapabilityFlag} this method * will always return {@code true}. * * <p> Requires Permission: @@ -1553,7 +1551,7 @@ public class ProvisioningManager { @WorkerThread @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE) public boolean getRcsProvisioningStatusForCapability( - @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability, + @ImsRcsManager.RcsImsCapabilityFlag int capability, @ImsRegistrationImplBase.ImsRegistrationTech int tech) { try { return getITelephony().getRcsProvisioningStatusForCapability(mSubId, capability, tech); @@ -1590,7 +1588,7 @@ public class ProvisioningManager { @WorkerThread @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) public void setRcsProvisioningStatusForCapability( - @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability, + @ImsRcsManager.RcsImsCapabilityFlag int capability, boolean isProvisioned) { try { getITelephony().setRcsProvisioningStatusForCapability(mSubId, capability, @@ -1622,7 +1620,7 @@ public class ProvisioningManager { @WorkerThread @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) public void setRcsProvisioningStatusForCapability( - @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability, + @ImsRcsManager.RcsImsCapabilityFlag int capability, @ImsRegistrationImplBase.ImsRegistrationTech int tech, boolean isProvisioned) { try { getITelephony().setRcsProvisioningStatusForCapability(mSubId, capability, @@ -1676,7 +1674,7 @@ public class ProvisioningManager { */ @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE) public boolean isRcsProvisioningRequiredForCapability( - @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability, + @ImsRcsManager.RcsImsCapabilityFlag int capability, @ImsRegistrationImplBase.ImsRegistrationTech int tech) { try { return getITelephony().isRcsProvisioningRequiredForCapability(mSubId, capability, tech); diff --git a/telephony/java/android/telephony/ims/RcsUceAdapter.java b/telephony/java/android/telephony/ims/RcsUceAdapter.java index 154bb11db5e3..91dc38ff9ddb 100644 --- a/telephony/java/android/telephony/ims/RcsUceAdapter.java +++ b/telephony/java/android/telephony/ims/RcsUceAdapter.java @@ -55,20 +55,28 @@ public class RcsUceAdapter { * This carrier supports User Capability Exchange as, defined by the framework using * SIP OPTIONS. If set, the RcsFeature should support capability exchange. If not set, this * RcsFeature should not publish capabilities or service capability requests. + * @deprecated Use {@link ImsRcsManager#CAPABILITY_TYPE_OPTIONS_UCE} instead. * @hide */ + @Deprecated public static final int CAPABILITY_TYPE_OPTIONS_UCE = 1 << 0; /** * This carrier supports User Capability Exchange as, defined by the framework using a * presence server. If set, the RcsFeature should support capability exchange. If not set, this * RcsFeature should not publish capabilities or service capability requests. + * @deprecated Use {@link ImsRcsManager#CAPABILITY_TYPE_PRESENCE_UCE} instead. * @hide */ + @Deprecated @SystemApi public static final int CAPABILITY_TYPE_PRESENCE_UCE = 1 << 1; - /**@hide*/ + /** + * @deprecated Use {@link ImsRcsManager.RcsImsCapabilityFlag} instead. + * @hide + */ + @Deprecated @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = "CAPABILITY_TYPE_", value = { CAPABILITY_TYPE_OPTIONS_UCE, diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java index ad2e9e133a11..fb0e659ec77b 100644 --- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java +++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java @@ -396,7 +396,7 @@ public class MmTelFeature extends ImsFeature { /** * Undefined capability type for initialization * This is used to check the upper range of MmTel capability - * {@hide} + * @hide */ public static final int CAPABILITY_TYPE_NONE = 0; @@ -427,7 +427,7 @@ public class MmTelFeature extends ImsFeature { /** * This is used to check the upper range of MmTel capability - * {@hide} + * @hide */ public static final int CAPABILITY_TYPE_MAX = CAPABILITY_TYPE_CALL_COMPOSER + 1; @@ -738,7 +738,7 @@ public class MmTelFeature extends ImsFeature { * Enabling/Disabling a capability here indicates that the capability should be registered or * deregistered (depending on the capability change) and become available or unavailable to * the framework. - * * @hide + * @hide */ @Override @SystemApi diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java index 70e4ef1f1a3a..843827befb65 100644 --- a/telephony/java/android/telephony/ims/feature/RcsFeature.java +++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java @@ -24,7 +24,7 @@ import android.annotation.SystemApi; import android.content.Context; import android.net.Uri; import android.os.RemoteException; -import android.telephony.ims.RcsUceAdapter; +import android.telephony.ims.ImsRcsManager; import android.telephony.ims.aidl.CapabilityExchangeAidlWrapper; import android.telephony.ims.aidl.ICapabilityExchangeEventListener; import android.telephony.ims.aidl.IImsCapabilityCallback; @@ -59,7 +59,9 @@ import java.util.function.Supplier; /** * Base implementation of the RcsFeature APIs. Any ImsService wishing to support RCS should extend * this class and provide implementations of the RcsFeature methods that they support. + * @hide */ +@SystemApi public class RcsFeature extends ImsFeature { private static final String LOG_TAG = "RcsFeature"; @@ -184,18 +186,22 @@ public class RcsFeature extends ImsFeature { * Contains the capabilities defined and supported by a {@link RcsFeature} in the * form of a bitmask. The capabilities that are used in the RcsFeature are * defined as: - * {RcsUceAdapter.RcsImsCapabilityFlag#CAPABILITY_TYPE_OPTIONS_UCE} - * {RcsUceAdapter.RcsImsCapabilityFlag#CAPABILITY_TYPE_PRESENCE_UCE} + * {@link ImsRcsManager.RcsImsCapabilityFlag#CAPABILITY_TYPE_OPTIONS_UCE} + * {@link ImsRcsManager.RcsImsCapabilityFlag#CAPABILITY_TYPE_PRESENCE_UCE} * * The enabled capabilities of this RcsFeature will be set by the framework - * using {#changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)}. + * using {@link #changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)}. * After the capabilities have been set, the RcsFeature may then perform the necessary bring up * of the capability and notify the capability status as true using - * {#notifyCapabilitiesStatusChanged(RcsImsCapabilities)}. This will signal to the + * {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)}. This will signal to the * framework that the capability is available for usage. */ public static class RcsImsCapabilities extends Capabilities { - /** @hide*/ + + /** + * Use {@link ImsRcsManager.RcsImsCapabilityFlag} instead in case used for public API + * @hide + */ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = "CAPABILITY_TYPE_", flag = true, value = { CAPABILITY_TYPE_NONE, @@ -226,7 +232,7 @@ public class RcsFeature extends ImsFeature { /** * This is used to check the upper range of RCS capability - * {@hide} + * @hide */ public static final int CAPABILITY_TYPE_MAX = CAPABILITY_TYPE_PRESENCE_UCE + 1; @@ -234,10 +240,8 @@ public class RcsFeature extends ImsFeature { * Create a new {@link RcsImsCapabilities} instance with the provided capabilities. * @param capabilities The capabilities that are supported for RCS in the form of a * bitfield. - * @hide */ - @SystemApi - public RcsImsCapabilities(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) { + public RcsImsCapabilities(@ImsRcsManager.RcsImsCapabilityFlag int capabilities) { super(capabilities); } @@ -249,30 +253,18 @@ public class RcsFeature extends ImsFeature { super(capabilities.getMask()); } - /** - * @hide - */ @Override - @SystemApi - public void addCapabilities(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) { + public void addCapabilities(@ImsRcsManager.RcsImsCapabilityFlag int capabilities) { super.addCapabilities(capabilities); } - /** - * @hide - */ @Override - @SystemApi - public void removeCapabilities(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) { + public void removeCapabilities(@ImsRcsManager.RcsImsCapabilityFlag int capabilities) { super.removeCapabilities(capabilities); } - /** - * @hide - */ @Override - @SystemApi - public boolean isCapable(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) { + public boolean isCapable(@ImsRcsManager.RcsImsCapabilityFlag int capabilities) { return super.isCapable(capabilities); } } @@ -288,9 +280,7 @@ public class RcsFeature extends ImsFeature { * Method stubs called from the framework will be called asynchronously. To specify the * {@link Executor} that the methods stubs will be called, use * {@link RcsFeature#RcsFeature(Executor)} instead. - * @hide */ - @SystemApi public RcsFeature() { super(); // Run on the Binder threads that call them. @@ -302,9 +292,7 @@ public class RcsFeature extends ImsFeature { * framework. * @param executor The executor for the framework to use when executing the methods overridden * by the implementation of RcsFeature. - * @hide */ - @SystemApi public RcsFeature(@NonNull Executor executor) { super(); if (executor == null) { @@ -335,10 +323,8 @@ public class RcsFeature extends ImsFeature { * requests. To change the status of the capabilities * {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)} should be called. * @return A copy of the current RcsFeature capability status. - * @hide */ @Override - @SystemApi public @NonNull final RcsImsCapabilities queryCapabilityStatus() { return new RcsImsCapabilities(super.queryCapabilityStatus()); } @@ -348,9 +334,7 @@ public class RcsFeature extends ImsFeature { * this signals to the framework that the capability has been initialized and is ready. * Call {@link #queryCapabilityStatus()} to return the current capability status. * @param capabilities The current capability status of the RcsFeature. - * @hide */ - @SystemApi public final void notifyCapabilitiesStatusChanged(@NonNull RcsImsCapabilities capabilities) { if (capabilities == null) { throw new IllegalArgumentException("RcsImsCapabilities must be non-null!"); @@ -367,11 +351,9 @@ public class RcsFeature extends ImsFeature { * @param capability The capability that we are querying the configuration for. * @param radioTech The radio technology type that we are querying. * @return true if the capability is enabled, false otherwise. - * @hide */ - @SystemApi public boolean queryCapabilityConfiguration( - @RcsUceAdapter.RcsImsCapabilityFlag int capability, + @ImsRcsManager.RcsImsCapabilityFlag int capability, @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) { // Base Implementation - Override to provide functionality return false; @@ -392,10 +374,8 @@ public class RcsFeature extends ImsFeature { * be called for each capability change that resulted in an error. * @param request The request to change the capability. * @param callback To notify the framework that the result of the capability changes. - * @hide */ @Override - @SystemApi public void changeEnabledCapabilities(@NonNull CapabilityChangeRequest request, @NonNull CapabilityCallbackProxy callback) { // Base Implementation - Override to provide functionality @@ -415,9 +395,7 @@ public class RcsFeature extends ImsFeature { * event to the framework. * @return An instance of {@link RcsCapabilityExchangeImplBase} that implements capability * exchange if it is supported by the device. - * @hide */ - @SystemApi public @NonNull RcsCapabilityExchangeImplBase createCapabilityExchangeImpl( @NonNull CapabilityExchangeEventListener listener) { // Base Implementation, override to implement functionality @@ -427,28 +405,20 @@ public class RcsFeature extends ImsFeature { /** * Remove the given CapabilityExchangeImplBase instance. * @param capExchangeImpl The {@link RcsCapabilityExchangeImplBase} instance to be destroyed. - * @hide */ - @SystemApi public void destroyCapabilityExchangeImpl( @NonNull RcsCapabilityExchangeImplBase capExchangeImpl) { // Override to implement the process of destroying RcsCapabilityExchangeImplBase instance. } - /**{@inheritDoc} - * @hide - */ + /**{@inheritDoc}*/ @Override - @SystemApi public void onFeatureRemoved() { } - /**{@inheritDoc} - * @hide - */ + /**{@inheritDoc}*/ @Override - @SystemApi public void onFeatureReady() { } 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 ac5565bea810..6fc1cc828a2c 100644 --- a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java @@ -93,7 +93,7 @@ public class ImsRegistrationImplBase { /** * This is used to check the upper range of registration tech - * {@hide} + * @hide */ public static final int REGISTRATION_TECH_MAX = REGISTRATION_TECH_NR + 1; @@ -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/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"; |